2009-12-12 65 views
13

我不知道这是一个哈希问题还是数组问题,但我不明白为什么在第三个示例中需要使用星号(*)符号来获取填充数据的散列。没有它,它会输出一个空的散列。为什么在数组之前需要星号?

# -*- coding: utf-8 -*- 
require 'pp' 
pp [[:first_name, 'Shane'], [:last_name, 'Harvie']] 
# => [[:first_name, "Shane"], [:last_name, "Harvie"]] 

pp [[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten 
# => [:first_name, "Shane", :last_name, "Harvie"] 

pp Hash[*[[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten] 
# => {:first_name=>"Shane", :last_name=>"Harvie"} 

pp Hash[[[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten] 
# => {} 

下面是该方法的说明。

--------------------------------------------------------------- Hash::[] 
    Hash[ [key =>|, value]* ] => hash 

    From Ruby 1.8 
------------------------------------------------------------------------ 
    Creates a new hash populated with the given objects. Equivalent to 
    the literal +{ _key_, _value_, ... }+. Keys and values occur in 
    pairs, so there must be an even number of arguments. 

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

回答

30

的图示符(即,*)变为否则将是一个数组为用于散列内分配的列表。您必须给[]运算符一个实际列表,以将其转换为散列的键/值对。 (请参阅下面的链接以获取splat操作符的简短描述(实际上可以这样做)(将数组展开成列表)或反向(将列表收集到数组中)。)

上面的操作方法,你给Hash[]奇数个项目,即单个数组。 (想想[[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten产生的结果,它产生[:first_name, 'Shane', :last_name, 'Havie']。)正如你引用的文档所说,[]运算符必须有偶数个元素。请注意,以下(虽然没用)工作:使用你上面的代码时

>> Hash[[[:first_name, 'Shane'], [:last_name, 'Harvie']].flatten, 1] 
=> {[:first_name, "Shane", :last_name, "Harvie"]=>1} 

(这是我不清楚为什么你没有得到“奇数哈希参数”错误 - 如你可以试试Hash[1]。)

一个简单的例子可能会使它更清晰。首先,传入一个项目,一个数组。对外开放与*数组手Hash[]的项目清单:

>> Hash[['foo', 'bar', 'bizz', 'buzz']] 
=> {} 
>> Hash[*['foo', 'bar', 'bizz', 'buzz']] 
=> {"foo"=>"bar", "bizz"=>"buzz"} 

this blog post一个更全面的解释。你也可能会发现this short write-up about the splat operator有用。

+0

非常感谢您的详细解释和链接。现在我完全明白这是什么。现在一切都很有意义。 – 2009-12-12 15:48:13

相关问题