我想知道为什么以下内容不会修改数组。
我有这个:
@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!在第二步中没有修改数组到位?或者方法的链接否定了我这样做的能力?欢呼声。
答案 0 :(得分:2)
tldr:如果该链中的每个方法都是一个就地修改方法,方法链只会修改对象。
案例中的重要区别在于您调用对象的第一种方法。您的第一个示例调用map!
这是一个修改数组的方法。 with_index
在此示例中并不重要,只会更改map!
的行为。
您的第二个示例在您的阵列上调用join
。 join
不会更改数组,但会返回一个完全不同的对象:一个字符串。然后你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。