如何在ruby中的可枚举上链接with_index和with_object?

时间:2017-01-14 05:23:54

标签: ruby enumerable ruby-block

我想处理数组['a', 'b', 'c']以返回字符串'0a1b2c'(即通过将每个索引与其值连接而形成的字符串)。

我可以这样做:

result = ''
['a', 'b', 'c'].each.with_index do |char, i|
  result += "#{i}#{char}"
end  
result

我想使用with_object消除块外的结果变量。

这样的事情:

['a', 'b', 'c'].each.with_index.with_object('') do |char, i, result|
  result += "#{i}#{char}"
end

但这会引发错误undefined method '+' for nil:NilClass

4 个答案:

答案 0 :(得分:2)

试试这个

arr.each.with_index.with_object('') { |(each, n), obj| ... }

这是如何运作的?

  • 同时应用with_indexwith_object会创建嵌套元组
  • (each, n), obj解包两个元组

有趣的事实 - 或者可能相当悲伤的事实 - 嵌套元组实际上被实现为一个短命数组,因此这将创建O(n)数组。如果这是一个关键的生产代码路径,我将把这两个枚举函数嵌套。因为你最有可能将obj分配给外部范围中的变量,所以将其重写为

是最有意义的。
obj = ''
arr.each_with_index { |each, n| ... }

答案 1 :(得分:2)

它没有使用你要求的方法,但它完成了工作并且相对紧凑:

array = ['a', 'b', 'c']
(0...array.size).zip(array).join
#=> "0a1b2c"

答案 2 :(得分:1)

两个操作都应该在不滥用each迭代器:

的情况下完成
%w|a b c|.map.with_index do |char, i|
  "#{i}#{char}"
end.join

%w|a b c|.each_with_object('').with_index do |(char, result), i|
  result << "#{i}#{char}"
end

或者,如果您仍想使用每个:

%w|a b c|.each.with_index.with_object('') do |char_idx, result|
  result << char_idx.join
end

答案 3 :(得分:0)

此解决方案很重要,这很不错:

%w|a b c|.each_with_object('').with_index do |(char, result), i|
  result << "#{i}#{char}"
end

在这里,我们使用<<代替+=

with_object仅适用于可变对象,您可能会认为该字符串是可变的,那么为什么我们不能使用+=?因为+=等效于x = x+y,所以它每次都会生成一个新对象。

最后,如果您将+=with_object一起使用,则永远不会突变您创建的原始对象,而只是创建一个新对象,您将不会在每次迭代时在该块中进行跟踪

此处有更多详细信息:How is each_with_object supposed to work?