Todd Benson
9/28/2008 4:00:00 PM
On Sun, Sep 28, 2008 at 6:42 AM, Andy Pipes <mypipeline@btinternet.com> wrote:
> Hi.
>
> Caveat: I'm just learning Ruby coming from some basic PHP programming.
>
> In the following I am aiming to peer into two tab-separated files with
> some vegetable facts on them. In the first 'column' of each file there
> are vegetable names, followed by the data. However, whilst some of the
> vegetables have the same name, others do not. My ultimate aim is to take
> the contents of each of these files, and merge them into a master file,
> and for those vegetables that have data in both files to merge the data.
>
> So a line from file 1 might read:
>
> Watermelon 60-80 4-10
>
> and one file two:
>
> Watermelon 1/2oz. 34 12-26 24-48
>
> and in the masterfile I would want:
>
> Watermelon 60-80 4-10 1/2oz. 34 12-26 24-48.
>
> I have been trying unsuccessfully for the past two days to do this so
> any help is greatly appreciated!!! :)
>
> Here's some sample code:
>
>
> File.foreach("vegetables.txt") do |line|
> name, temp, germ_days = line.split /\t/
> #split min and max germination temps
> if temp =~ /-/
> temp_min, temp_max = temp.split /-/
> else temp_min = temp and temp_max = temp
> end
> # split the min and max germ days
> if germ_days =~ /-/
> germ_days_min, germ_days_max = germ_days.split /-/
> else germ_days_min = germ_days and germ_days_max = germ_days
> end
>
> # now iterate over the other table
> File.foreach("vegetables2.txt") do |l|
> name2, crop_yield, space_between_rows, space_between_plants,
> days_to_harvest = l.split /\t/
> #split min and max space between rows
> if space_between_rows =~ /-/
> space_between_rows_min, space_between_rows_max =
> space_between_rows.split /-/
> else
> space_between_rows_min = space_between_rows and
> space_between_rows_max = space_between_rows
> end
> # split the min and max space between plants
> if space_between_plants =~ /-/
> space_between_plants_min, space_between_plants_max =
> space_between_plants.split /-/
> else
> space_between_plants_min = space_between_plants and
> space_between_plants_max = space_between_plants
> end
> # split the min and max days to harvest
> if days_to_harvest =~ /-/
> days_to_harvest_min, days_to_harvest_max = days_to_harvest.split
> /-/
> else
> days_to_harvest_min = days_to_harvest and days_to_harvest_max =
> days_to_harvest
> end
> if name2 == name
> veggies = {
> :name => name2,
> :crop_yield => crop_yield,
> :temp_min => temp_min,
> :temp_max => temp_max,
> :germ_days_min => germ_days_min,
> :germ_days_max => germ_days_max,
> :space_between_plants_min => space_between_plants_min,
> :space_between_plants_max => space_between_plants_max,
> :space_between_rows_min => space_between_rows_min,
> :space_between_rows_max => space_between_rows_min,
> :days_to_harvest_min => days_to_harvest_min,
> :days_to_harvest_max => days_to_harvest_max
> }
> end
>
> puts veggies
>
> end
> end
>
> If I run this, I get local variable not found errors; I've tried a lot
> of variations, with no luck. I'm new to OO, and think that maybe I'm
> just 'not getting it' in this case.
>
> Can anyone help? Thanks in advance.
>
> Andy
For scope, you must establish for the interpreter that these variables
exist outside of the File.foreach blocks.
my_var = ""
File.foreach {|line| #do_something_with_my_var}
Personally, I might try using ranges (needs cleaning up)...
#add method to range for building from
# a string like "1-10"
class Range
def self.[](str)
begin
a = str.split(/-/)
a[1] ||= [0]
new(*(a.map {|i| Integer(i)})) rescue str
end
end
end
#just a method to split and change to ranges
def collate_veggie str
str.chomp.split(/\t/).map! {|elem| Range[elem]}
end
#first set of data
veggies1 = {}
keys1 = :temp, :germ_days
File.foreach('veggies1.txt' ) do |line|
values = collate_veggie line
veggies1[values.shift] = keys1.zip values
end
#second set of data
veggies2 = {}
keys2 = :crop_yield, :row_space, :plant_space, :harvest_days
File.foreach('veggies2.txt') do |line|
values = collate_veggie line
veggies2[values.shift] = keys2.zip values
end
#merge the two
veggies = {}
veggies1.each_key {|k| veggies[k] = Hash[*(veggies1[k] | veggies2[k]).flatten]}
#use Range methods for min and max
p h
p h["Watermelon"][:germ_days].min
p h["JuicyVeggie"][:plant_space].max
just a thought,
Todd