7

我不确定下面的代码片段到底发生了什么。

>> a, b = ["ho", "hey"]
=> ["ho", "hey"]
>> a
=> "ho"
>> b
=> "hey"    
>> c, d = "foo", "bar"
=> ["foo", "bar"]
>> c 
=> "foo"
>> d
=> "bar"
>> a, b = ["blerg"], ["baz"]
=> [["blerg"], ["baz"]]
>> a
=> ["blerg"]
>> b 
=> ["baz"]

为什么第 1 行不返回a => ["ho"]

a, b = ["ho", "hey"]那么在幕后,这三个赋值( , c, d = "foo", "bar", a, b = ["blerg"], ["baz"])有什么区别呢?

4

4 回答 4

11
a, b = ["ho", "hey"] 

a分配数组的第一个元素,即字符串“ho”。没什么奇怪的。

a, b = ["blerg"], ["baz"]

a, b = [["blerg"], ["baz"]]

这两个是相同的,从它们的返回值可以看出。所以 a 被分配了第一个元素,它是一个包含一个元素的数组:["blerg"]

相似地,

c, d = "foo", "bar"

是相同的

c, d = ["foo", "bar"]
于 2013-02-16T18:48:35.043 回答
7

在 Ruby 中,= 左侧是变量列表,右侧是表达式列表。它将第一个变量分配给第一个表达式的值,将第二个变量分配给第二个表达式的值,依此类推。如果变量多于表达式,剩余的变量将被赋值nil

> a, b, c, d = "foo", 2+3, Array.new(2, 3), [:c, :d]
> a     # => "foo"
> b     # => 5
> c     # => [3, 3]
> d     # => [:c, :d]
> e     # => nil

有两个例外:

左侧只有一个变量,右侧有多个表达式

在这种情况下,上面的规则会说变量只是被设置为右边第一个表达式的值。相反,该变量被设置为由右侧表达式的值组成的数组。在下面的示例中,我们看到a获取值[:b, :c],而不仅仅是:b

> a = :b, :c
> a    # => [:b, :c]

这相当于:

> *a = :b , :c
> a    # => [:b, :c]

另一个例外:

左边有多个变量,右边只有一个表达式它是一个数组

同样,原始规则意味着第一个变量被设置为整个数组,其余变量将为 nil。但是,该数组实际上最终会被其元素列表替换,然后=恢复为开头描述的“默认”行为:

> a, b, c = [:d, [:e, :f]]
> a    # => :d
> b    # => [:e, :f]
> c    # => nil

这相当于a, b, c = *[:d, [:e, :f]],或者只是a, b, c = :d, [:e, :f]

于 2013-02-16T20:23:38.493 回答
0

在您指出的示例中,多重赋值的右侧使用了 2 种不同的结构:

来自简单数组的多重赋值

array = ["item1", "item2"]
a, b = array
# a => "item1"
# b => "item2"

来自数组的多重赋值,其元素本身就是单元素数组(又名:多维数组)

array = [["item1"], ["item2"]]
a, b = array
# a => ["item1"]
# b => ["item2"]

多重赋值仅展开多维数组的第一级,并允许您将这些元素分配给表达式左侧的多个变量。因此,当您使用多维数组执行此操作时,它会获取第一个元素["item1"]并将其分配给a,然后移动到下一个元素,即["item2"]并将其分配给b。多重赋值不会“深入”到多维数组中,它从第一级元素执行赋值。

于 2013-02-16T18:55:49.727 回答
0

Ruby 语言中的赋值运算符允许多重赋值 (又名:并行赋值)。

对赋值运算符 (=) 左侧的左侧变量或属性说值,对右侧值说右值。

通过多次赋值,您可以将一个逗号分隔列表分配给另一个,左侧的相应变量从右侧获取相应的值

第一次并行分配

a, b = ["ho", "hey"]

如果最后一个右值是一个数组,你可以在它前面加上一个星号,这可以有效地将它扩展成它的组成值如果右值是右侧唯一的东西,则不需要星号,数组将自动展开

为了更好地理解,试试这个:

>> a,b,c =  "1",*["ho", "hey"]
=> ["1", "ho", "hey"]
>> a
=> "1"
>> b
=> "ho"
>> c
=> "hey"

让我们再看看:

>> a,b,c =  "1",["ho", "hey"]
=> ["1", ["ho", "hey"]]
>> a
=> "1"
>> b
=> ["ho", "hey"]
>> c
=> nil

如您所见,如果我们不使用 * 作为数组前缀,则不会扩展数组。

第二次并行分配

c, d = "foo", "bar"

"foo", "bar" 是分配给左侧相应变量的两个文字字符串。

第三次并行分配

a, b = ["blerg"], ["baz"])?

["blerg"]并且["baz"] 是两个数组,每个数组包含一个String类的元素;

因此,每个“单个字符串的数组”都分配给左侧的相应变量。

于 2013-02-16T19:47:55.957 回答