splat 运算符的意外结果
Unexpected result with splat operator
我有一个散列,其值是一个大小为 1
:
的数组
hash = {:start => [1]}
我想解压数组,如下所示:
hash.each_pair{ |key, value| hash[key] = value[0] } # => {:start=>1}
我认为下面的 *
-operator 可以工作,但它没有给出预期的结果:
hash.each_pair{ |key, value| hash[key] = *value } # => {:start=>[1]}
为什么 *value
return [1]
而不是 1
?
因为应用于 hash
的 []=
方法除了密钥(放在 []
部分内)之外只接受一个参数,并且 splatted/expanded array,它通常是一系列值(在这种特殊情况下恰好是单个元素)不能直接接受为 splatted 的参数。所以它毕竟被[]=
的参数接受为一个数组。
换句话说,([]=
方法的)参数必须是一个对象,但是splatted元素(例如:foo, :bar, :baz
)不是对象。将它们解释为对象的唯一方法是将它们放回数组中(例如 [:foo, :bar, :baz]
)。
使用 splat 运算符,你可以这样做:
hash.each_pair{|key, value| hash.[]= key, *value}
因为Ruby在这里表现的出乎意料的聪明。
是的,splash 运算符将 "fold" 和 "unfold" 一个数组,但代码中的问题是您对扇形值所做的操作。
考虑此代码:
array = ['a', 'b']
some_var = *array
array # => ['a', 'b']
如您所见,splat 运算符似乎对您的数组没有任何作用,而这:
some_var, some_other_var = *array
some_var # => "a"
somet_other_var # => "b"
会如您所愿。
似乎 ruby 只是 "figures" 如果你将一个数组拼成一个变量,你想要的是数组,而不是值。
编辑:正如 sawa 在评论中指出的那样,hash[key] =
与 variable =
不同。 []=
是 Hash 的一个实例方法,其内部有自己的 C 代码,这在某些情况下可能(理论上)会导致不同的行为。我不知道有什么例子,但这并不意味着有 none。
但是为了简单起见,我们可以假设常规变量赋值的行为与 hash[key] =
.
完全相同
sawa 和 Ninigi 已经指出了为什么作业没有按预期工作。这是我的尝试。
Ruby 的赋值功能无论您是赋值给变量、常量还是通过使用赋值运算符隐式调用赋值方法(如 Hash#[]=
)都有效。为了简单起见,我在以下示例中使用了一个变量。
在赋值中使用 splat 运算符 解压数组,即
a = *[1, 2, 3]
被评估为:
a = 1, 2, 3
但是 Ruby 还允许您通过列出多个值在赋值期间隐式创建数组。因此,以上又等价于:
a = [1, 2, 3]
这就是为什么 *[1]
导致 [1]
- 它被解包,只是为了转换回数组。
元素可以使用多重赋值单独赋值:
a, b = [1, 2, 3]
a #=> 1
b #=> 2
或者只是:
a, = [1, 2, 3]
a #=> 1
您可以在您的代码中使用它(注意 hash[key]
之后的逗号):
hash = {:start => [1]}
hash.each_pair { |key, values| hash[key], = values }
#=> {:start=>1}
但还有另一种更优雅的方法:您可以通过在数组参数两边加上括号来解包数组:
hash = {:start => [1]}
hash.each_pair { |key, (value)| hash[key] = value }
#=> {:start=>1}
括号将分解数组,将第一个数组元素分配给value
。
我有一个散列,其值是一个大小为 1
:
hash = {:start => [1]}
我想解压数组,如下所示:
hash.each_pair{ |key, value| hash[key] = value[0] } # => {:start=>1}
我认为下面的 *
-operator 可以工作,但它没有给出预期的结果:
hash.each_pair{ |key, value| hash[key] = *value } # => {:start=>[1]}
为什么 *value
return [1]
而不是 1
?
因为应用于 hash
的 []=
方法除了密钥(放在 []
部分内)之外只接受一个参数,并且 splatted/expanded array,它通常是一系列值(在这种特殊情况下恰好是单个元素)不能直接接受为 splatted 的参数。所以它毕竟被[]=
的参数接受为一个数组。
换句话说,([]=
方法的)参数必须是一个对象,但是splatted元素(例如:foo, :bar, :baz
)不是对象。将它们解释为对象的唯一方法是将它们放回数组中(例如 [:foo, :bar, :baz]
)。
使用 splat 运算符,你可以这样做:
hash.each_pair{|key, value| hash.[]= key, *value}
因为Ruby在这里表现的出乎意料的聪明。
是的,splash 运算符将 "fold" 和 "unfold" 一个数组,但代码中的问题是您对扇形值所做的操作。
考虑此代码:
array = ['a', 'b']
some_var = *array
array # => ['a', 'b']
如您所见,splat 运算符似乎对您的数组没有任何作用,而这:
some_var, some_other_var = *array
some_var # => "a"
somet_other_var # => "b"
会如您所愿。
似乎 ruby 只是 "figures" 如果你将一个数组拼成一个变量,你想要的是数组,而不是值。
编辑:正如 sawa 在评论中指出的那样,hash[key] =
与 variable =
不同。 []=
是 Hash 的一个实例方法,其内部有自己的 C 代码,这在某些情况下可能(理论上)会导致不同的行为。我不知道有什么例子,但这并不意味着有 none。
但是为了简单起见,我们可以假设常规变量赋值的行为与 hash[key] =
.
sawa 和 Ninigi 已经指出了为什么作业没有按预期工作。这是我的尝试。
Ruby 的赋值功能无论您是赋值给变量、常量还是通过使用赋值运算符隐式调用赋值方法(如 Hash#[]=
)都有效。为了简单起见,我在以下示例中使用了一个变量。
在赋值中使用 splat 运算符 解压数组,即
a = *[1, 2, 3]
被评估为:
a = 1, 2, 3
但是 Ruby 还允许您通过列出多个值在赋值期间隐式创建数组。因此,以上又等价于:
a = [1, 2, 3]
这就是为什么 *[1]
导致 [1]
- 它被解包,只是为了转换回数组。
元素可以使用多重赋值单独赋值:
a, b = [1, 2, 3]
a #=> 1
b #=> 2
或者只是:
a, = [1, 2, 3]
a #=> 1
您可以在您的代码中使用它(注意 hash[key]
之后的逗号):
hash = {:start => [1]}
hash.each_pair { |key, values| hash[key], = values }
#=> {:start=>1}
但还有另一种更优雅的方法:您可以通过在数组参数两边加上括号来解包数组:
hash = {:start => [1]}
hash.each_pair { |key, (value)| hash[key] = value }
#=> {:start=>1}
括号将分解数组,将第一个数组元素分配给value
。