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

4

受到这个问题的启发,我尝试使用并行赋值和数组、方法调用互相搭配。下面是一个典型的例子,尝试通过值来交换数组中的两个成员:

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


并行赋值很有用,但对于这种需要在继续之前查找数组中变量位置的任务来说,哈希表似乎是一种更可用的结构,因为它可以直接查找。如果您需要重复执行赋值操作,例如在内部循环中,那么使用哈希表会更加高效。 - the Tin Man
同意,这里的例子是假设的,部分取自其他问题。 - Mladen Jablanović
现在我已经根据你的问题创建了一个问题! - Andrew Grimm
你应该立即放下手头的工作,转向函数式编程! - Andrew Grimm
@Greg:我已经恢复了标题,我真的不认为问题的形式是正确的。在命名我的问题时,我遵循这个简单的原则:“我如何表达我想匹配我的SO问题的Google查询”。 - Mladen Jablanović
3个回答

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

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

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=哈希方法,它甚至可以更加简洁:
h.values_at('dog', 'cat') = h.values_at('cat', 'dog')

但是,不幸的是,我们没有。哈希切片是 Perl 中非常强大的工具,也是我在 Ruby 中想念的东西。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接