Ruby splat运算符:Array(1..10).equal? [* Array(1..10)] =>假?

时间:2017-03-10 21:23:56

标签: arrays ruby splat

我在看:

hash_1 = Hash[*[Array("a".."j"), Array(1..10)].transpose.flatten]

所以我想,有或没有啪啪声的回报," *"看起来都一样 - 为什么

hash_1 = Hash[[Array("a".."j"), Array(1..10)].transpose.flatten]会返回{}吗?

因此,当我测试 Array(1..10).equal? [*Array(1..10)] =>假

因此

Hash[Array(1..10)] => {}

Hash[*Array(1..10)] => {1 => 2,3 => 4,5 => 6,7 => 8,9 => 10}

请帮忙。

3 个答案:

答案 0 :(得分:1)

哈希[]

Hash[]需要偶数个参数(或一个类似哈希的参数):

Hash['a','b']
# {"a"=>"b"}

Hash[['a','b']]
# {}

在第二个例子中,只有一个参数:一个包含两个字符串的数组,它不回答to_hash。根据Ruby版本,它将显示警告或引发ArgumentError

带有splat的哈希[]

对于你的例子:

Hash[*Array(1..10)]

与:

相同
Hash[1,2,3,4,5,6,7,8,9,10]
# {1=>2, 3=>4, 5=>6, 7=>8, 9=>10}

这是偶数个参数,因此可以在每对中创建一个Hash。

请注意,使用奇数个参数:

 Hash[1,2,3,4,5,6,7,8,9]
 # ArgumentError: odd number of arguments for Hash

答案 1 :(得分:1)

Documentation for Ruby Hash's [] method表示你可以提供1)将用作键和值的值对,2)子数组形式的键值对数组,或3)可转换为的对象哈希。使用splat的Hash[*Array(1..10)]与第一个案例匹配,irb中的快速实验将显示:

irb(main):001:0> Hash.new([1,2])
=> {}

生成Hash,其默认值为[1,2],但不包含任何元素。当你使用Hash[Array(1..10)]时,即使用splat时,这就是可以被传递的对象。

从Ruby 2.4开始,您会收到以下警告:

irb(main):002:0> Hash[[1,2]]
(irb):2: warning: wrong element type Integer at 0 (expected array)
(irb):2: warning: ignoring wrong elements is deprecated, remove them explicitly
(irb):2: warning: this causes ArgumentError in the next release
(irb):2: warning: wrong element type Integer at 1 (expected array)
(irb):2: warning: ignoring wrong elements is deprecated, remove them explicitly
(irb):2: warning: this causes ArgumentError in the next release

答案 2 :(得分:1)

您的代码存在另一个问题,或者更确切地说是您的探索性测试,到目前为止在其他答案中没有提到:

BasicObject#equal?是真的,如果参数是与接收者相同的对象。不是“具有相同值的对象”,而不是“具有相同表示的对象”,只有它是完全相同的对象。换句话说,要使equal?成立,只涉及一个单一对象 接收器参数。在您的情况下,有两个对象(即使它们具有相同的值和相同的表示),因此equal? 永远不会返回true。

您不应该使用equal?。面向对象编程的基本原则之一就是对象可以模拟其他对象(事实上,OO是用模拟语言发明的),但equal?允许你区分真实对象及其模拟,因此它打破了OO。我再说一遍:测试参考相等性会使你的代码成为非OO。坦率地说,它甚至不可能在一个“真正的”OO语言中,并且让我很遗憾Ruby拥有它(尽管Java更糟糕,在Java中它甚至是默认的平等行为)。

你应该(几乎)总是使用==,这是语义值相等。在极少数情况下,您可以使用eql?(严格值相等)。在Ruby核心库和标准库本身中,eql?仅与hash一起用于散列和类似行为。 (事实上​​,我可以想到的唯一三个地方,在Ruby中使用eql?HashSet(和SortedSet),以及类似集合数组操作(Array#uniqArray#uniq!Array#&Array#|Array#-)。)切勿使用equal?

注意:===完全是一个不同的野兽,与平等无关。 (对于不平等的东西,使用三个等号来表示这是一个不幸的名字。)