在循环中更改数组中的条目

时间:2011-02-21 08:35:22

标签: ruby arrays

arr = ["red","green","blue","yellow"]

arr.each do |colour|
  if colour == "red"
    colour = "green"
  end
end

puts arr.inspect

以上代码输出:

["red", "green", "blue", "yellow"]

但为什么不呢?

["green", "green", "blue", "yellow"]

我认为颜色是对数组中当前元素的引用,无论我对它做什么都会影响该数组元素?

4 个答案:

答案 0 :(得分:5)

当您在arr.each块内时,colour变量绑定到arr数组中的一个对象。

但是,只要在块中进行赋值colour = "green",现在colour变量就绑定到一个新对象(即一个值为"green"的String),并且原arr保持不受影响。

实现您所谈论的内容的一种方法是:

arr.each_index do |i|
  arr[i] = "green" if arr[i] == "red"
end

直接操纵数组。

答案 1 :(得分:4)

Color实际上是对数组中当前元素的引用,但是'color =“green”'它现在引用了一个 new 字符串。旧的保持不变。要进行试验,请尝试替换

colour = "green"

有一个或多个

colour.replace "green"
colour.capitalize! #not capitalize, which would give a new string again
colour << "ish"

所有这些都在现有字符串上运行,而不是创建新字符串。

答案 2 :(得分:4)

通常,为了将数组转换为另一个数组,在Ruby中不使用each方法,而是使用map方法(上面的用户sflinter代码):

arr.map { |x| x == "red" ? "green" : x }

或者,考虑到转换图,更为一般:

mapping = {'red' => 'green', 'blue' => 'yellow'}

我们可以做类似

的事情
p arr.map {|e| mapping[e] || e} # => ["green", "green", "yellow", "yellow"]
PS:正如Phrogz在下面建议的那样,map创建了一个新的数组实例,如果你打算将修改后的数组保存在同一个变量中,你应该为它分配map的结果。

另一方面,map的邪恶双胞胎称为map!,它原位修改原始阵列(因此无需将其分配回来),节省了一些空间和时间,但是打破功能不应有副作用的纯函数式编程概念。

答案 3 :(得分:2)

我要编写的是 not 建议的方法,但请注意,由于Strings在Ruby中是可变的,因此您可以编写原始代码,如下所示:

arr.each do |colour|
  colour.replace "green" if colour == "red"
end

p arr
#=> ["green", "green", "blue", "yellow"]