使用并行赋值交换数组元素

这个问题引起了我的兴趣,我用数组和方法调用进行了并行分配。 所以这是一个典范示例,试图通过它们的值交换数组中的两个成员:

deck = ['A', 'B', 'C'] #=> ["A", "B", "C"] deck[deck.index("A")], deck[deck.index("B")] = deck[deck.index("B")], deck[deck.index("A")] #=> ["B", "A"] deck #=> ["A", "B", "C"] 

arrays没有改变。 但是如果我们改变参数的顺序,它就有效:

 deck[deck.index("B")], deck[deck.index("A")] = deck[deck.index("A")], deck[deck.index("B")] #=> ["A", "B"] deck #=> ["B", "A", "C"] 

我想它与在赋值中调用index方法的顺序有关,但是没有清楚地看到它。 有人可以解释下面的事情的顺序,以及为什么第一个例子没有交换成员,第二个例子呢?

这是预料之中的。 它遵循ruby如何评估表达式。

 deck[deck.index("A")], deck[deck.index("B")] = deck[deck.index("B")], deck[deck.index("A")] 

暗示

 deck[deck.index("A")], deck[deck.index("B")] = 'B', 'A' 

注意:此处的字符串“A”和“B”仅供参考。 Ruby不会在这里创建新的字符串对象 。 基本上是:

 deck[deck.index("A")] = 'B' -> deck[0] = 'B' (deck = ['B', 'B', 'C']) deck[deck.index("B")] = 'A' -> deck[0] = 'A' (deck = ['A', 'B', 'C']) 

Array #index在找到第一个匹配项时返回。

现在,

 deck[deck.index("B")], deck[deck.index("A")] = deck[deck.index("A")], deck[deck.index("B")] -> deck[deck.index("B")], deck[deck.index("A")] = 'A', 'B' -> deck[deck.index("B")] = 'A' -> deck[1] = 'A' (deck = ['A', 'A', 'C']) -> deck[deck.index("A")] = 'B' -> deck[0] = 'B' (deck = ['B', 'A', 'C']) 

举个例子,比较用于搜索数组的机制,找到正确的索引然后交换值,使用Hash可以做什么:

 h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" } h['dog'], h['cat'] = h.values_at('cat', 'dog') h #=> {"cat"=>"canine", "dog"=>"feline", "cow"=>"bovine"} 

现在,如果Ruby有一个可values_at= Hash方法,它可能更清晰:

 h.values_at('dog', 'cat') = h.values_at('cat', 'dog') 

但是,唉,我们没有。 Hash切片是Perl中非常强大的工具,我想念Ruby。

而且,是的,我知道我可以添加自己的assignable values_at=

M Rajesh是正确的,但他实际上必须考虑才能解决这个问题。 我太懒了!

这是一个printf调试方式,显示发生了什么。

 deck = ['A', 'B', 'C'] #=> ["A", "B", "C"] deck[deck.index("A").tap {|index| STDERR.puts "Result of indexing for #{"A".inspect} is #{index.inspect}" }], deck[deck.index("B").tap {|index| STDERR.puts "Result of indexing for #{"B".inspect} is #{index.inspect}" }] = deck[deck.index("B")], deck[deck.index("A")] # Result of indexing for "A" is 0 # Result of indexing for "B" is 0 #=> ["B", "A"] deck #=> ["A", "B", "C"]