¿Cómo fusiona ordenadamente N matrices ordenadas (u otras estructuras de datos similares a listas) en Ruby? Por ejemplo, en Python usaría heapq.merge. Debe haber algo como esto integrado en Ruby, ¿verdad?Combinar matrices ordenadas N en ruby perezosamente
Respuesta
Terminé escribiéndolo usando las estructuras de datos de la gema 'algoritmo'. No fue tan malo como esperaba.
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
No, no hay nada integrado para hacer eso. Al menos, nada que salte al instante a la mente. Sin embargo, hubo un GSoC project para implementar los tipos de datos relevantes hace un par de años, que podría utilizar.
Parece que el montón funcionaría, excepto por el hecho de que no es flojo. Lástima, gracias por la sugerencia, los otros algoritmos pueden ser útiles más tarde. – guidoism
Aquí hay una solución (ligeramente golfizada) que debería funcionar en arreglos de cualquier colección 'lista-como' que soporte #first
, #shift
y #empty?
. Tenga en cuenta que es destructivo: cada llamada al lazymerge
elimina un elemento de una colección.
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
Salida:
[[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= [[]]
Tenga en cuenta también que este algoritmo también es vago sobre el mantenimiento de la propiedad del montículo - no se mantiene entre las llamadas. Esto probablemente hace que trabaje más de lo necesario, ya que realiza una heapificación completa en cada llamada posterior. Esto podría solucionarse haciendo un heapify completo una vez en el frente, luego llamando al minheap(a,0)
antes de la línea return r
.
Aquí hay una implementación que debería funcionar en cualquier Enumerable, incluso infinitos. Devuelve el Enumerador.
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. ¿Cómo combinar secuencias ordenadas?
- 2. Combinar listas ordenadas en Python
- 3. Mediana de 5 matrices ordenadas
- 4. Cómo combinar una colección de preferencias ordenadas
- 5. Combinar dos matrices en Hash
- 6. ¿Generar ordenadas aleatoriamente ordenadas sin el género? O (n)
- 7. Combinar dos matrices en JavaScript
- 8. PHP: Combinar matrices multidimensionales
- 9. ¿Están ordenadas las matrices asociativas de PHP?
- 10. combinar dos matrices
- 11. La intersección de dos matrices ordenadas
- 12. Combinar dos matrices de manera limpia en ActionScript (3.0)?
- 13. más cercano suma par de dos matrices ordenadas
- 14. ¿Cómo puedo combinar matrices PHP?
- 15. Combinar dos matrices de enteros
- 16. Combinar dos matrices en una matriz en python y ordenar
- 17. ¿Cómo ordenar una matriz m x n que tiene todas sus m filas ordenadas y n columnas ordenadas?
- 18. Matrices limitadas en Ruby
- 19. Ruby fusionando dos matrices en una
- 20. Concatenar valores de n matrices en php
- 21. BST a partir de dos matrices no ordenadas
- 22. Combinar 2 matrices de diferentes longitudes
- 23. matlab - cómo combinar/entrelazar 2 matrices?
- 24. Ruby: matrices asociativas
- 25. uso práctico de matrices n-dimensional, donde (N> 3)
- 26. probar el algoritmo que usa min-heap para combinar k listas ordenadas
- 27. Combina las entradas ordenadas en Haskell?
- 28. Combinar dos matrices como pares clave de valor en PHP
- 29. Combinar eficientemente matrices de cadenas en .NET, manteniendo distintos valores
- 30. ¿Cómo combinar varias matrices en una lista usando Linq?
Enfoque interesante para mantener el contexto de la cola. El único inconveniente es que el código crea un nuevo objeto Array para cada extracción de valor, lo que hace que funcione para el recolector de basura. – Sim