如何在Ruby中懶散地合併N個排序的數組(或其他類列表數據結構)?例如,在Python中,您可以使用heapq.merge。 Ruby中必須有這樣的內容,對吧?在Ruby中懶散地合併N個排序的數組
5
A
回答
1
我最終自己使用'算法'gem中的數據結構來編寫它。這並沒有我想象的那麼糟糕。
require 'algorithms'
class LazyHeapMerger
def initialize(sorted_arrays)
@heap = Containers::Heap.new { |x, y| (x.first <=> y.first) == -1 }
sorted_arrays.each do |a|
q = Containers::Queue.new(a)
@heap.push([q.pop, q])
end
end
def each
while @heap.length > 0
value, q = @heap.pop
@heap.push([q.pop, q]) if q.size > 0
yield value
end
end
end
m = LazyHeapMerger.new([[1, 2], [3, 5], [4]])
m.each do |o|
puts o
end
0
不,沒有什麼內置的做到這一點。至少,沒有什麼會立即想到。然而,幾年前有一個GSoC project來實現相關的數據類型,您可以使用它。
+0
它看起來像堆會工作,除非它不是懶惰的事實。太糟糕了,謝謝你的建議,其他算法可能會在稍後派上用場。 – guidoism 2011-04-25 22:33:22
1
下面是一個(略golfed)解決方案,應該在支持#first
,#shift
,並#empty?
任何名單樣「收藏的數組。請注意,它具有破壞性 - 每次撥打lazymerge
時,都會從一個集合中刪除一個項目。
def minheap a,i
r=(l=2*(m=i)+1)+1 #get l,r index
m = l if l< a.size and a[l].first < a[m].first
m = r if r< a.size and a[r].first < a[m].first
(a[i],a[m]=a[m],a[i];minheap(a,m)) if (m!=i)
end
def lazymerge a
(a.size/2).downto(1){|i|minheap(a,i)}
r = a[0].shift
a[0]=a.pop if a[0].empty?
return r
end
p arrs = [ [1,2,3], [2,4,5], [4,5,6],[3,4,5]]
v=true
puts "Extracted #{v=lazymerge (arrs)}. Arr= #{arrs.inspect}" while v
輸出:
[[1, 2, 3], [2, 4, 5], [4, 5, 6], [3, 4, 5]]
Extracted 1. Arr= [[2, 3], [2, 4, 5], [4, 5, 6], [3, 4, 5]]
Extracted 2. Arr= [[3], [2, 4, 5], [4, 5, 6], [3, 4, 5]]
Extracted 2. Arr= [[4, 5], [3], [4, 5, 6], [3, 4, 5]]
Extracted 3. Arr= [[4, 5], [3, 4, 5], [4, 5, 6]]
Extracted 3. Arr= [[4, 5], [4, 5], [4, 5, 6]]
Extracted 4. Arr= [[5], [4, 5], [4, 5, 6]]
Extracted 4. Arr= [[5], [5], [4, 5, 6]]
Extracted 4. Arr= [[5, 6], [5], [5]]
Extracted 5. Arr= [[6], [5], [5]]
Extracted 5. Arr= [[5], [6]]
Extracted 5. Arr= [[6]]
Extracted 6. Arr= [[]]
Extracted . Arr= [[]]
還要注意,這種算法也懶得保持堆的特性 - 它不保持通話之間。這可能會導致它做更多的工作,因爲它會在每次後續的呼叫中完成堆積。這可以通過先完成一次完整的堆垛來修復,然後在return r
之前呼叫minheap(a,0)
。
1
這是一個應該在任何Enumerable上工作的實現,甚至是無限的。它返回枚舉器。
def lazy_merge *list
list.map!(&:enum_for) # get an enumerator for each collection
Enumerator.new do |yielder|
hash = list.each_with_object({}){ |enum, hash|
begin
hash[enum] = enum.next
rescue StopIteration
# skip empty enumerators
end
}
loop do
raise StopIteration if hash.empty?
enum, value = hash.min_by{|k,v| v}
yielder.yield value
begin
hash[enum] = enum.next
rescue StopIteration
hash.delete(enum) # remove enumerator that we already processed
end
end
end
end
Infinity = 1.0/0 # easy way to get infinite range
p lazy_merge([1, 3, 5, 8], (2..4), (6..Infinity), []).take(12)
#=> [1, 2, 3, 3, 4, 5, 6, 7, 8, 8, 9, 10]
相關問題
- 1. 合併大小爲n的k個排序數組的下界
- 2. 合併排序來排序n值數組
- 3. 合併排序的數組
- 4. 在Ruby中對組合進行排序
- 5. 合併排序不排序數組
- 6. 爲什麼在合併排序中合併操作是O(n)?
- 7. ruby - 懶惰地遍歷數組
- 8. Ruby中的遞歸合併排序
- 9. 合併兩個數組的散列
- 10. 排序數組的數組中的Ruby
- 11. 在Ruby中排序和操作散列
- 12. 合併排序 - 僅排序2^n個元素
- 13. 使用合併排序對n個字符串進行排序
- 14. Ruby修改並在散列數組中添加散列值
- 15. 在懶惰地圖集合中按日期快速排序
- 16. 在ruby中排序數組的語法
- 17. 排序數組在PHP中,合併兩個值加在一起
- 18. 合併多個Ruby散列屬性
- 19. 合併排序算法合併兩個數組中的第三個條件
- 20. 合併兩個數組,合併排序風格
- 21. 歸併排序在Ruby中
- 22. 合併排序 - 使用Int數組排序字符串數組
- 23. 排序合併數組組成的排序陣列
- 24. 合併排序2個未排序數組
- 25. 組合兩個數組並對數組進行排序Swift
- 26. 如何合併兩個排序後的數組以在C++中形成另一個排序後的數組?
- 27. Ruby中的n路文件合併
- 28. 合併不等長的排序數組
- 29. 合併/排序我的數組(Java)
- 30. 就地合併排序
保持隊列上下文有趣的方法。唯一的缺點是代碼爲每個值拉創建一個新的Array對象,這使得垃圾回收器工作。 – Sim 2013-01-24 01:29:52