为什么带有字符串数组的ruby并行赋值返回字符串

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

>> 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"] )?

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

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

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

这两个是相同的,你可以通过它们的返回值看到。 所以给a分配了第一个元素,它是一个带有一个元素的数组: ["blerg"]

同样的,

 c, d = "foo", "bar" 

是相同的

 c, d = ["foo", "bar"] 

在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] 

另一个例外:

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

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

 > 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]

在您指出的示例中,在多个赋值的右侧使用了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 。 多重赋值不会“深入”到多维数组中,它会从第一级元素执行赋值。

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

假设左侧变量或属性在赋值运算符(=)的左侧左右,并将右侧称为左值。

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

第一次并行分配

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

如果最后一个rvalue是一个数组,你可以在它前面添加一个星号,它可以有效地将其扩展为其组成值 。 如果rvalue是右侧唯一的数据将自动扩展,则不需要星号。

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

 >> 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"]是两个Array,每个Array包含一个String类的元素;

因此,每个“sigle String的数组”被分配给左侧的相应变量。