Reputation: 97
Beginner question:
I have code like this:
p true_columns
=> [["1", "88", "59"], ["2", "79", "63"], ["3", "77", "55"], ["4", "77", "59"], ["5", "90", "66"], ["6", "81", "61"], ["7", "73", "57"], ["8", "75", "54"], ["9", "86", "32*"], ["10", "84", "64"], ["11", "91", "59"], ["12", "88", "73"], ["13", "70", "59"], ["14", "61", "59"], ["15", "64", "55"], ["16", "79", "59"], ["17", "81", "57"], ["18", "82", "52"], ["19", "81", "61"], ["20", "84", "57"], ["21", "86", "59"], ["22", "90", "64"], ["23", "90", "68"], ["24", "90", "77"], ["25", "90", "72"], ["26", "97*", "64"], ["27", "91", "72"], ["28", "84", "68"], ["29", "88", "66"], ["30", "90", "45"]]
My problem is to be able to split up this data into a list, and be able to find the Min/Max of the differences between the second and third values of each of the arrays within the big set. Not the cleanest code, but bear with me:
true_columns.each do |data|
difference = data[1].to_i - data[2].to_i
difference_string = difference.to_s.split(" ")
print difference_string
end
=> ["29"]["16"]["22"]["18"]["24"]["20"]["16"]["21"]["54"]["20"]["32"]["15"]["11"]["2"]["9"]["20"]["24"]["30"]["20"]["27"]["27"]["26"]["22"]["13"]["18"]["33"]["19"]["16"]["22"]["45"]
Any kind of min/max/[x] command will return something that reduces "difference_string" into something more basic, concatenating the original difference_string. Example:
print difference_string.min
=> 2916221824201621542032151129202430202727262213183319162245
I believe that has something to do with the original variable being Fixnum form, and I'm not sure how to convert that into a list, with which I can pull something like difference_string.min. Also, if anyone could give me an explanation for why the min/max commands reduce the data into the above form, that would be awesome.
Edit:
For reference, my code at the top was:
file = File.open("file.dat")
columns = []
file.each_line do |line|
p line
columns << line.split(" ")[0 , 3]
end
Upvotes: 0
Views: 192
Reputation: 80075
difference_string = difference.to_s.split(" ")
At that point, difference
is an integer (20). It gets converted to a string ("20"), which is split on a space. Since there is no space in the string, the result will be something like ["20"], which is an array with one element.
Calling '.min' on that will result in "20"
. Printing that will , ehh, print it, without a line ending.
There is a method min_max_by
available to all enumerables (like arrays):
min_col, max_col = true_cols.minmax_by{|data| data[1].to_i - data[2].to_i} #["14", "61", "59"] and ["9", "86", "32*"]
Upvotes: 0
Reputation: 35531
The problem is not related to Fixnum
. It's because you aren't moving the results into an array that can handle all of them - rather you are working on one result at a time. This should work for you:
true_columns.map{|data| data[1].to_i - data[2].to_i}.min
What this does is build a new array by 'mapping' the difference for each data row as an element in the new array. You then call .min
on the new array to find the minimum element.
Upvotes: 1
Reputation: 156534
Look at the Ruby Enumerable#map
and Enumerable#reduce
methods (which are both available for arrays), they will help you transform your array into something you need.
For example, here is how you could find both the min and max in one pass using "reduce":
min_max = true_columns.reduce({}) do |acc, data|
diff = data[1].to_i - data[2].to_i
acc[:min] = diff if (!acc[:min] || (diff < acc[:min]))
acc[:max] = diff if (!acc[:max] || (diff > acc[:max]))
acc
end
min_max # => {:min=>2, :max=>54}
Upvotes: 0