Iterate over sorted enumerables preserving order
# Iterate over sorted enumerables preserving order
# across all of them yielding items in globally-sorted order.
def sorted_iterate(*enums, with_index: false)
unless block_given?
return enum_for(__method__, *enums, with_index: with_index)
end
unless with_index
return send(__method__, *enums, with_index: true) { |v, _| yield v }
end
index = enums.map.with_index { |e, i| [i, e] }.to_h
loop do
peeked = []
index.select! do |i, e|
peeked << [e.peek, e, i]
rescue StopIteration
false
end
break if peeked.empty?
min = peeked.min_by(&:first)
yield min[1].next, min[2]
end
end
Better optimized, no indexes
# If you have multiple sorted enumerables, this function will lazy-iterate
# across all of them yielding items in globally-sorted order.
def sorted_iterate(*enums)
return enum_for(__method__, *enums) unless block_given?
buffers = enums.map { |e| [e, []] }
loop do
buffers.select! do |enum, value|
!value.empty? || (value << enum.next)
rescue StopIteration
false
end
break if buffers.empty?
yield buffers.min_by(&:last)[1].pop
end
end
Code snippets in this post are covered by 0BSD License.