Ruby:如何在以下示例中使用Enumerator?

时间:2014-02-02 02:59:07

标签: ruby enumerator

我似乎无法以微不足道的方式使用枚举器。 也许它实际上比我意识到的更有限。

这是一个例子,我认为枚举器很方便,但无法实现它们:

设array = [0,1,2,“+”,4]。

我有兴趣创建以下Enumerator-behavior:

  1. 遍历数组
  2. 产生所有不是“+”的对象
  3. 如果是“+”,则删除该元素和前两个元素, 产生它们的总和,并将枚举序列重置为 开始。
  4. 也许问题是我不能“删除”已经产生的东西?换句话说,我不能不屈服?我对这种行为很感兴趣,因为它能够在改变数组之后在任何给定位置倒回序列(这会扰乱迭代的顺序)。

2 个答案:

答案 0 :(得分:0)

Enumerator没有previous方法,它不允许您在迭代时跳过值,并且它没有删除元素的方法。

因此,我认为您无法使用您发布的确切工作流程执行所需操作,但我确信可以创建您可能偏离工作流程时所寻求的行为。

答案 1 :(得分:0)

摘要 - 此选项似乎符合您所表达的标准:

[0, 1, 2, "+", 4].inject([]) { |n,e| n << (e == "+" ? n.pop(2).reduce(:+) : e) }
# => [0, 3, 4]

以下是我的想法......

选项1:

使用each_with_index,这样您就可以轻松识别以前的元素。

array.each_with_index do |element, index|
  your_logic_here
end

选项2:

或者为了避免改变数组,你可以简单地构建一个像这样的新数组:

new_array = []
array.each do |element|
  if element == "+"
    ele_sum = new_array.pop(2)
    new_array << (ele_sum.reduce :+)
  else
    new_array << element
  end
end

如果你没有发现它令人困惑,你可以将if语句中的两行合并到:

new_array << new_array.pop(2).reduce(:+)

或者如果你对三元运算符没问题,可以将整个事情缩短为:

def some_function(array)
  new_array = []
  array.each { |element| new_array << (element == "+" ? new_array.pop(2).reduce(:+) : element) }
end

> array = [0, 1, 2, "+", 4]
> some_function(array)
# => [0, 3, 4]

在irb中工作和测试

...或者当然使用注入然后你可以全部内联:

array.inject([]) { |new_array, element| new_array << (element == "+" ? new_array.pop(2).reduce(:+) : element) }

[0, 1, 2, "+", 4].inject([]) { |n,e| n << (e == "+" ? n.pop(2).reduce(:+) : e) }
# => [0, 3, 4]

但我更喜欢扩展版本的可读性