使用splat运算符时出现意外结果

时间:2015-09-15 10:56:23

标签: ruby splat

我有一个哈希值,其值是一个大小为1的数组:

hash = {:start => [1]}

我想解压缩数组,如:

hash.each_pair{ |key, value| hash[key] = value[0] } # => {:start=>1}

并且我认为* - 运算符如下所示,但它没有给出预期的结果:

hash.each_pair{ |key, value| hash[key] = *value } # => {:start=>[1]}

为什么*value会返回[1]而不是1

3 个答案:

答案 0 :(得分:3)

因为应用于[]=的{​​{1}}方法除了密钥(放在hash部分内)之外只接受一个参数,并且是一个splatted / expanded数组,这是通常,一系列值(在这种特殊情况下恰好恰好是单个元素)不能直接被接受为splatted的参数。所以它被[]的参数接受为一个数组。

换句话说,([]=方法的)参数必须是对象,但是splatted元素(例如[]=)不是对象。将它们解释为对象的唯一方法是将它们放回到数组中(例如:foo, :bar, :baz)。

使用splat运算符,您可以这样做:

[:foo, :bar, :baz]

答案 1 :(得分:3)

因为Ruby在这里表现得非常聪明。

是的,泼水操作员将"折叠"并且"展开"一个数组,但你的代码中的catch是你用这个扇形值做的。

考虑此代码:

array = ['a', 'b']
some_var = *array
array # => ['a', 'b']

正如你所看到的那样,splat运算符似乎对你的数组没有任何作用,而这个:

some_var, some_other_var = *array
some_var # => "a"
somet_other_var # => "b"

会做你期望的事情。

看来红宝石只是"数字"如果将数组展开为单个变量,则需要数组,而不是值。

编辑:正如sawa在评论中指出的那样,hash[key] =variable =不同。 []=是哈希的一个实例方法,它拥有自己的C代码,在某些情况下可能导致不同的行为(理论上)。我不知道任何例子,但这并不意味着没有。 但为了简单起见,我们可以假设常规变量赋值与hash[key] =完全相同。

答案 2 :(得分:3)

sawa和Ninigi已经指出了为什么作业没有按预期工作。这是我的尝试。

Ruby的赋值功能无论您是分配给变量,常量还是通过赋值运算符隐式调用 int main() { int size,i; cout<<"Please enter the size of the array"; cin>>size; int *array_=new int [size]; cout<<"Please enter all elements of the array"; for(i=0;i<size;i++){ cin>>array_[i]; } insertion(&array_,size); return 0; } void insertion(int *array_[],int size){ int i; for(i=0;i<size;i++){ cout<<*array_[i]; } } 之类的赋值方法,都可以正常工作。为简单起见,我在以下示例中使用了变量。

在赋值中使用splat运算符解包数组,即

Hash#[]=

评估为:

a = *[1, 2, 3]

但Ruby还允许您通过列出多个值在赋值期间隐式创建数组。因此,上述内容相当于:

a = 1, 2, 3

这就是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}