(一元)* 运算符在这段 Ruby 代码中做了啥?

Posted

技术标签:

【中文标题】(一元)* 运算符在这段 Ruby 代码中做了啥?【英文标题】:What does the (unary) * operator do in this Ruby code?(一元)* 运算符在这段 Ruby 代码中做了什么? 【发布时间】:2010-10-29 10:34:58 【问题描述】:

给定 Ruby 代码

line = "first_name=mickey;last_name=mouse;country=usa" 
record = Hash[*line.split(/=|;/)] 

除了* 运算符之外,我了解第二行中的所有内容 - 它在做什么,相关文档在哪里? (正如您可能猜到的那样,事实证明搜索这个案例很困难......)

【问题讨论】:

【参考方案1】:

*splat 运算符。

它将Array 扩展为参数列表,在本例中为Hash.[] 方法的参数列表。 (更准确地说,它会扩展任何响应 to_ary/to_a 或 Ruby 1.9 中的 to_a 的对象。)

为了说明,以下两个语句是等价的:

method arg1, arg2, arg3
method *[arg1, arg2, arg3]

它也可以在不同的上下文中使用,以捕获方法定义中所有剩余的方法参数。在这种情况下,它不会扩展,而是合并:

def method2(*args)  # args will hold Array of all arguments
end

Some more detailed information here.

【讨论】:

一般来说,当在类似 LHS 的情况下使用时(任何时候你在一个值上调用它),splat 将一个数组拆分为单独的值,并且在类似 RHS 的情况下使用(任何时候你在一些以前未定义的变量上使用它),它将单独的值分组到一个数组中。所以a,b,*c = d,e,f,*g 设置 a=d, b=e, 和 c=[f,g0,g1,g2,...,gn],其中 g=[g0,g1,g2,...,gn]跨度> 为了完整起见,splat 运算符根据 David A. Black 在“The Well Grounded Rubyist”中使用的术语将数组转换为裸列表 @rampion:很棒的评论,你刚刚混合了 LHS 和 RHS。反之亦然。【参考方案2】:

splat 运算符解压缩传递给函数的数组,以便将每个元素作为单独的参数发送给函数。

一个简单的例子:

>> def func(a, b, c)
>>   puts a, b, c
>> end
=> nil

>> func(1, 2, 3)  #we can call func with three parameters
1
2
3
=> nil

>> list = [1, 2, 3]
=> [1, 2, 3]

>> func(list) #We CAN'T call func with an array, even though it has three objects
ArgumentError: wrong number of arguments (1 for 3)
    from (irb):12:in 'func'
    from (irb):12

>> func(*list) #But we CAN call func with an unpacked array.
1
2
3
=> nil

就是这样!

【讨论】:

【参考方案3】:

正如每个人都提到的,这是一个“splat”。寻找 Ruby 语法是不可能的,我在其他问题中也问过这个问题。这部分问题的答案是您在

上搜索
asterisk in ruby syntax

在谷歌中。 Google 随时为您服务,只需将您所见即所得。

Anyhoo,就像很多 Ruby 代码一样,这些代码非常密集。

line.split(/=|;/)

创建一个包含六个元素的数组,first_name, mickey, last_name, mouse, country, usa。然后使用 splat 将其变成哈希。现在 Ruby 人总是派你去看 Splat 方法,因为一切都暴露在 Ruby 中。我不知道它在哪里,但是一旦你有了它,你会看到它通过数组运行for 并构建散列。

您可以在core 文档中查找代码。如果你找不到它(我找不到),你会尝试编写一些这样的代码(它可以工作,但不是 Ruby-like 代码):

line = "first_name=mickey;last_name=mouse;country=usa"
presplat = line.split(/=|;/)
splat = Hash.new
for i in (0..presplat.length-1)
    splat[presplat[i]] = presplat[i+1] if i%2==0
end

puts splat["first_name"]

然后 Ruby 帮将能够告诉您为什么您的代码愚蠢、糟糕或完全错误。

如果您已经阅读了这么多,请阅读Hash 初始化文档。

基本上,使用多个参数初始化的哈希将它们创建为键值对:

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

因此,在您的示例中,这将导致以下哈希:

"first_name"=>"mickey", "last_name"=>"mouse", "county"=>"usa"

【讨论】:

以上是关于(一元)* 运算符在这段 Ruby 代码中做了啥?的主要内容,如果未能解决你的问题,请参考以下文章

||= 在Ruby中做了啥[重复]

逗号运算符在“eval()”中做了啥?

Batch-API:我在这段代码中做错了啥?

*::(星号双冒号)在Ruby中做了啥?

“^=”运算符在这个查找非成对数算法中做了啥? [复制]

^= 在 python 中做了啥[关闭]