具有起始索引的排列

时间:2013-06-04 08:17:56

标签: ruby permutation

我为我的算法生成了一组相当大的数组排列:

argeArray.permutation(permSize) do |perm|
  # Do something with perm
end

现在我正在努力更新应用程序,以便能够在停止的索引处继续。

经过一番调查后,我没有找到具有起始索引的permutation替代方法(能够跳过0..startIndex)。

接下来,我发现drop() method能够切断排列枚举器中的第一个元素数量:

startIndex = 3000000000 # skip first 3 billion combinations
argeArray.permutation(permSize).drop(startIndex) do |perm|
  # Do something with perm
end

但实验表明,这会创建完整的组合,但由于需要 lot lot 的内存,因此效率不高。 ..即使它只需要跳过前30亿个组合......

另一种解决方案是跳过算法,直到达到startIndex

startIndex = 3000000000 # skip first 3 billion combinations
argeArray.permutation(permSize).with_index() do |perm, index|
  next if index < startIndex # Skip until startIndex is reached
  # Do something with perm
end

缺点是在算法(最终)开始工作之前测试了30亿个组合(并浪费地检查是否达到startIndex

这个问题还有其他(更有效的)解决方案吗?以某种方式能够告诉permutation()跳过初始数量的组合? (假设它总是使用相同的顺序)

1 个答案:

答案 0 :(得分:1)

Ruby 2.0引入了Enumerator::Lazy。也许调查可能对你有所帮助。

module Enumerable
  def filter_map(&block)
    map(&block).compact
  end
end

class Enumerator::Lazy
  def filter_map
    Lazy.new(self) do |yielder, *values|
      result = yield *values
      yielder << result if result
    end
  end
end

(1..Float::INFINITY).lazy.filter_map{|i| i*i if i.even?}.first(5)
    # => [4, 16, 36, 64, 100]

您可以将您的排列设置为Enumerator::Lazy的实例,并使用drop跳转到某个位置。