我正在使用方法Array#product
和几个大数组参数。接收器也是一个大阵列。因此,结果数组很大,并占用了过多的内存。我需要产生的所有组合,但我不需要它们在单个阵列中。
我想知道是否有替代方法可以使用更少的内存。计算时间并不是真正的问题。
答案 0 :(得分:0)
您可以使用product
的块形式(请参见https://apidock.com/ruby/Array/product)。
例如,以下内容使我的红宝石处理无法响应,因此我必须kill -9
:
list = Array.new(100_000)
list.product list
不过,我可以control+c
使用阻止形式随时将其停止:
list.product(list) do |combination|
puts combination.join(",")
end
答案 1 :(得分:0)
让我开始计算两个数组乘积的问题。稍后,我将解决更普遍的问题。
arr1 = [1,2,3]
arr2 = [4,5,6]
arr1.product(arr2)
#=> [[1, 4], [1, 5], [1, 6], [2, 4], [2, 5],
# [2, 6], [3, 4], [3, 5], [3, 6]]
要减少内存需求(即避免构造上述数组),可以构造一个枚举器。
product_enum = Enumerator.new do |y|
arr1.size.times do |i|
e1 = arr1[i]
arr2.size.times { |j| y << [e1, arr2[j]] }
end
end
#=> #<Enumerator: 3<Enumerator::Generator:0x00...20>:each>
loop do
p product_enum.next
end
[1, 4]
[1, 5]
[1, 6]
[2, 4]
[2, 5]
[2, 6]
[3, 4]
[3, 5]
[3, 6]
要重用枚举器,请执行product_enum.rewind
。请参见Enumerator::new和Enumerator#rewind。 Enumerator::new
的块变量y
被称为 yielder 。枚举器可以被认为是根据某些规则生成值的机器。
Ruby的方法Array#combination,Array#permutation和其他方法返回枚举数,但是由于我不知道的原因,Array#product返回一个数组。 (也许读者可以在评论中解释原因。)
我们可以构造一个Array
方法product_enum
,该方法返回一个枚举器,您可以将其用于解决问题。
class Array
def product_enum(*arr)
Enumerator.new do |y|
self.size.times do |i|
e1 = self[i]
product_enum_recurse(y,[e1],*arr)
end
end
end
def product_enum_recurse(y,a,*arr)
v, *rest = arr
v.size.times do |i|
if rest.empty?
y << [*a, v[i]]
else
product_enum_recurse(y,[*a, v[i]],*rest)
end
end
end
end
e = [1,2].product_enum([3,4], [5,6], [7,8])
#=> #<Enumerator: #<Enumerator::Generator:0x00...0>:each>
loop do
p e.next
end
[1, 3, 5, 7]
[1, 3, 5, 8]
[1, 3, 6, 7]
[1, 3, 6, 8]
[1, 4, 5, 7]
[1, 4, 5, 8]
[1, 4, 6, 7]
[1, 4, 6, 8]
[2, 3, 5, 7]
[2, 3, 5, 8]
[2, 3, 6, 7]
[2, 3, 6, 8]
[2, 4, 5, 7]
[2, 4, 5, 8]
[2, 4, 6, 7]
[2, 4, 6, 8]