2010-11-15 38 views
4

深受this question的影響,我在數組和方法調用中扮演了一點平行賦值的角色。所以這裏是一個範例,試圖通過它們的值交換數組中的兩個成員:使用並行賦值交換數組元素

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

該數組沒有更改。但是,如果我們改變參數的順序,它的工作原理:

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

我猜它與調用分配中的index方法的順序做,但不能看清楚。有人可以解釋下面的事情的順序,爲什麼第一個例子不交換成員,第二個呢?

+0

並行任務是有用的,但對於這種任務,在那裏你會繼續之前查找數組中的變量的位置好像一個Hash是因爲它直接查找的更有用的結構。如果你重複地執行你的任務,就像在內部循環中一樣,這將會很昂貴,並且散列會超出它。 – 2010-11-15 15:07:37

+0

同意,這裏的例子是假設的,部分來自另一個問題。 – 2010-11-15 15:55:24

+0

現在我已經根據您的問題創建了一個問題! – 2010-12-02 23:43:07

回答

3

預計。它來自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']) 

陣列#指數收益率。

現在,

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']) 
+0

現在明白了,謝謝! – 2010-11-15 10:38:37

1

只是作爲一個例子,比較用來搜索陣列的陰謀,找到正確的索引然後交換值,你可以使用一個哈希做什麼:

h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" } 

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

h #=> {"cat"=>"canine", "dog"=>"feline", "cow"=>"bovine"} 

現在,如果紅寶石有一個分配values_at=哈希方法可能是更清潔:

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

但是,唉,我們沒有。哈希分片是Perl中一個非常強大的工具,我錯過了Ruby。

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

1

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