What's the 'Ruby Way' to Iterate Over Two Arrays at Once

What's the 'Ruby way' to iterate over two arrays at once

>> @budget = [ 100, 150, 25, 105 ]
=> [100, 150, 25, 105]
>> @actual = [ 120, 100, 50, 100 ]
=> [120, 100, 50, 100]

>> @budget.zip @actual
=> [[100, 120], [150, 100], [25, 50], [105, 100]]

>> @budget.zip(@actual).each do |budget, actual|
?> puts budget
>> puts actual
>> end
100
120
150
100
25
50
105
100
=> [[100, 120], [150, 100], [25, 50], [105, 100]]

Best way to iterate over multiple arrays?

The zip method on array objects:

a.zip b do |items|
puts items[0], items[1]
end

Ruby code to iterate through two array simulataneoulsy

You can use zip function for example like this :

array1.zip(array2).each do |array1_var, array2_var|
## whatever you want to do with array_1var and array_2 var
end

How to loop over two arrays and create a map in Ruby

If what you need is an array of hashes, where every hash has the keys shape and color, then you can use product between array1 and array2 and then just map the result of that:

array1.product(array2).map { |shape, color| { shape: shape, color: color } }
# [{:shape=>"square", :color=>"red"}, {:shape=>"square", :color=>"blue"}, {:shape=>"circle", :color=>"red"}, {:shape=>"circle", :color=>"blue"}, {:shape=>"triagle", :color=>"red"}, {:shape=>"triagle", :color=>"blue"}]

How do I iterate through two arrays individually

Okay here is what I ended up coming up with. I believe that it should work for you, with the following implementation:

  • If the current line from each file starts with a parseable date, then the oldest wins (change the < on line 49 to > to swap that).
  • When a line is written to the output, the file that line was read from is cycled and the next line is grabbed. The line from the other file stays intact until that line has its turn to be written.
  • If a line does not start with a parseable date, that line wins and is written. As stated above, that file is cycled and the next line is pulled in, repeating until there is a parseable date again or it hits the end of the file.
  • If one of the files reaches its end, the other file will be streamed to the output until it also reaches its output.

Please note that you will need to change 'file1', 'file2', and 'output' to file paths, relative or absolute. You can use ARGV or OptionParser to use command line arguments to pass this data into the program.

Input files:

# file1

2014-06-21 07:20:25,654 file1 text2
2015-01-13 14:24:23,654 file1 text1
test text1 belongs to the row above
2015-06-21 08:57:27,654 file1 text3

# file2

2013-01-05 19:27:25,654 file1 text2
2015-04-01 10:13:23,654 file1 text1
test text5 belongs to the row above
2015-06-23 09:49:27,654 file1 text3

# output

2013-01-05 19:27:25,654 file1 text2
2014-06-21 07:20:25,654 file1 text2
2015-01-13 14:24:23,654 file1 text1
test text1 belongs to the row above
2015-04-01 10:13:23,654 file1 text1
test text5 belongs to the row above
2015-06-21 08:57:27,654 file1 text3
2015-06-23 09:49:27,654 file1 text3

# compile_files.rb

require 'date'

# Attempt to read a line from the supplied file.
# If this fails, we are at the end of the file and return nil.
def read_line_from_file(file)
file.readline
rescue EOFError
nil
end

# Parse the date which is at the beginning of the supplied text.
# If this fails, it doesn't start with a date so we return nil.
def parse_date(text)
DateTime.parse(text)
rescue ArgumentError
nil
end

begin
# Open the files to sort
input_file_1 = File.open('file1', 'r')
input_file_2 = File.open('file2', 'r')

# Open the file that will be written. Here it is named "output"
File.open('output', 'w+') do |of|
# Read the first line from each file
left = read_line_from_file(input_file_1)
right = read_line_from_file(input_file_2)

# Loop until BOTH files have reached their end
until left.nil? && right.nil?
# If the first file was successfully read,
# attempt to parse the date at the beginning of the line
left_date = parse_date(left) if left
# If the second file was successfully read,
# attempt to parse the date at the beginning of the line
right_date = parse_date(right) if right

# If the first file was successfully read,
# but the date was not successfully parsed,
# the line is a stack trace and needs to be printed
# because it will be following the related
# timestamped line.
if left && left_date.nil?
of << left

# Now that we have printed that line,
# grab the next one from the same file.
left = read_line_from_file(input_file_1)
next

# If the first file was successfully read,
# but the date was not successfully parsed,
# the line is a stack trace and needs to be printed
# because it will be following the related
# timestamped line.
elsif right && right_date.nil?
of << right

# Now that we have printed that line,
# grab the next one from the same file.
right = read_line_from_file(input_file_2)

# Skip straight to the next iteration of the `until` loop.
next
end

if left.nil?
of << right

# Now that we have printed that line,
# grab the next one from the same file.
right = read_line_from_file(input_file_2)

# Skip straight to the next iteration of the `until` loop.
next
end

# If we got this far, neither of the lines were stack trace
# lines. If the second file has reached its end, we need
# to print the line we grabbed from the first file.
if right.nil?
of << left

# Now that we have printed that line,
# grab the next one from the same file.
left = read_line_from_file(input_file_1)

# Skip straight to the next iteration of the `until` loop.
next
end

# ADDED THIS SECTION
# If we got this far, the second file has not
# reached its end. If the first file has reached
# its end, we need to print the line we grabbed
# from the second file.
if left.nil?
of << right

# Now that we have printed that line,
# grab the next one from the same file.
right = read_line_from_file(input_file_2)

# Skip straight to the next iteration of the `until` loop.
next
end

# If we got this far, neither file has reached its
# end and both start with timestamps. If the first file's
# timestamp is less, it is older.
if left_date < right_date
of << left

# Now that we have printed that line,
# grab the next one from the same file.
left = read_line_from_file(input_file_1)

# Skip straight to the next iteration of the `until` loop.
next
# Either the timestamps were the same or the second one is
# older.
else
of << right

# Now that we have printed that line,
# grab the next one from the same file.
right = read_line_from_file(input_file_2)

# Skip straight to the next iteration of the `until` loop.
next
end
end
end
ensure
# Make sure that the file descriptors are close.
input_file_1.close
input_file_2.close
end

Ruby: iterate over two array of hashes and create array of arrays

You could use nested each to compare each item in both arrays, grabbing the ids for those items that match the conditions; for example:

rtg.each_with_object([]) do |r, result|
inv.each do |i|
if i[:position_id] == r[:position_id] && i[:date].between?(r[:valid_from], r[:valid_to])
result << [r[:id], i[:id]]
end
end
end

#=> [[7, 23], [6, 17]]


Related Topics



Leave a reply



Submit