在并行赋值中删除值

Drop value in parallel assignment

既然可以这样并行赋值,

x, y, z = [1, 2, 3]

我想知道是否可以删除 y 值。有没有一种方法可以在不污染当前范围的命名空间的情况下进行并行赋值?

我尝试分配给 nil:

x, nil, z = [1, 2, 3]

但这不起作用。

惯用的方法是将其分配给名为下划线的变量:

x, _, z = [1, 2, 3]

如果要删除多个值,可以使用 splat:

x, *_, z = [1, 2, 3, 4, 5]

如@ndn所述,经常使用_

忽略它并重新分配它是可以的,但是_仍然是当前作用域的命名空间中的一个变量:

l = [1, 2, 3]

x, _, z = l
puts _
#=> 2

如果它困扰你,你可以使用:

x, z = l.values_at(0,-1)

虽然它可能不太可读。如果您在脚本上启动 rubocop_ 也是建议的语法。

关于可读性,如果你想解释这个变量是什么,但又想表明以后不会用到它,你可以使用:

x, _y, z = [1, 2, 3]
# Do something with x and z. Ignore _y

也是rubocop提出的:

test.rb:2:4: W: Useless assignment to variable - y. Use _ or _y as a variable name to indicate that it won't be used.

我更愿意改进@ndn 答案并仅使用 * 符号来删除值。 _ 通常用于 return 最后一个值,因此在这里使用它可能会造成混淆。

所以你可以使用

x, *, z = [1, 2, 3]

以及

x, *, y, z = [1, 2, 3, 4]

它仍然会理解你和return所有变量的正确值。

meschi 询问是否可以使用并行赋值将数组中的部分(但不是全部)元素赋值给变量。

首先,写

没有帮助
a, _, c = [1, true, 2]

因为 _ 是一个变量:

_ #=> true

(使用 IRB 不会得到这个结果,因为 IRB 将 _ 用于自己的目的。)

如果在上面的数组中,你只想将1true分配给你可以写的变量

a, b, * = [1, true, 2]
a #=> 1
b #=> true

如果只想将12赋值给变量,可以这样写

a, *, b = [1, true, 2]
a #=> 1
b #=> 2

如果对于数组 [1, true, 2, 3],您只想将 12 分配给变量,那么,这是一个问题。显然,正如@Eric 在评论中指出的那样,您需要编写

a, b, b, * = [1, true, 2, 3]
a #=> 1
b #=> 2

这个想法当然可以推广:

a, b, b, b, c, c = [1, true, 2, 3, 4, 5]
a #=> 1
b #=> 3
c #=> 5

这是个好主意吗?这不是问题。

主要问题可能是创建了一个不被使用的变量,然后无意中使用了它,如下所示:

a, _, b = [1, true, 2]
...
launch_missiles_now?(_)

如果是这样,有几个选项。一种是简单地将表达式包装在一个方法中,从而将多余的变量严格限制:

def get_a_and_b(arr)
  a, _, b, _ = arr
  [a, b]
end

a, b = get_a_and_b [1, true, 2, 3]
  #=> [1, 2]

另一种是命名不需要的变量,使其不太可能被意外引用,例如:

a, _reference_this_variable_and_you_will_die, b = [1, true, 2]