修改一个数组 - Ruby

时间:2014-09-04 20:31:30

标签: ruby arrays loops enumerable iterate

我想知道为什么以下内容不会修改数组。

我有这个:

@card.map!.with_index {|value, key|  key.even? ? value*=2 : value}

只是迭代一个数组,并将所有偶数键的值加倍。

然后我这样做:

@card.join.split('').map!{|x| x.to_i}

将数组连接成一个巨大的数字,将它们分成单个数字,然后将它们映射回数组中的整数。从第一步到第二步的唯一真正变化是步骤1看起来像a = [1,2,12],第二步看起来像a = [1,2,1,2]。第二步,即使我使用.map!当我p @card它在第一步之后看起来完全相同。如果我想继续使用新数组,我必须设置第二步=某些东西。为什么是这样?是.map!在第二步中没有修改数组到位?或者方法的链接否定了我这样做的能力?欢呼声。

2 个答案:

答案 0 :(得分:2)

tldr:如果该链中的每个方法都是一个就地修改方法,方法链只会修改对象。

案例中的重要区别在于您调用对象的第一种方法。您的第一个示例调用map!这是一个修改数组的方法。 with_index在此示例中并不重要,只会更改map!的行为。

您的第二个示例在您的阵列上调用joinjoin不会更改数组,但会返回一个完全不同的对象:一个字符串。然后你split创建一个新数组的字符串,以下map!修改 new 数组。

因此,在第二个示例中,您需要再次将结果分配给变量:

@card = @card.join.split('').map{ |x| x.to_i }

可能还有其他方法可以计算出所需的结果。但由于您没有提供输入和输出示例,因此不清楚您要实现的目标。

答案 1 :(得分:2)

  

.map!在第二步中不修改数组?

是的,确实如此,但它修改的数组不是@card。 split()方法返回一个新数组,即一个不是@card的数组,并映射!修改新阵列。

检查出来:

tap{|x|...} → x
Yields [the receiver] to the block, and then returns [the receiver]. 
The primary purpose of this method is to “tap into” a method chain, 
in order to perform operations on intermediate results within the chain.  

@card = ['a', 'b', 'c']
puts @card.object_id

@card.join.split('').tap{|arr| puts arr.object_id}.map{ |x| x.to_i }  #arr is whatever split() returns

--output:--
2156361580
2156361380

ruby​​程序中的每个对象都有一个唯一的object_id。