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

时间:2010-11-15 08:48:51

标签: ruby arrays parallel-assignment

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方法的顺序有关,但没有清楚地看到它。有人可以解释下面的事情的顺序,以及为什么第一个例子没有交换成员,第二个例子呢?

3 个答案:

答案 0 :(得分: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'])

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

答案 1 :(得分:1)

举个例子,比较用于搜索数组的阴谋,找到正确的索引,然后交换值,使用哈希可以做的事情:

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。

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

答案 2 :(得分: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"]