0

I am trying to swap two elements in an array like this

deck = []
(deck << (1..52).to_a << 'A' << 'B').flatten!
p deck
deck[deck.index("A")], deck[deck.index("B")] = deck[deck.index("B")], deck[deck.index("A")] #swap "A" and "B"
p deck

But it doesnt swap. If i do this, however:

deck[52], deck[53] = deck[53], deck[52]

it works. Any suggestions?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
badmaash
  • 4,775
  • 7
  • 46
  • 61
  • 2
    This isn't related to your question, but just a suggesiton: You can write the code to create the array much more simply as `deck = (1..52).to_a + ['A', 'B']`. – Chuck Nov 15 '10 at 06:13
  • For the benefit of all readers of this question (esp. future readers), please specify the Ruby version you are using (1.8.x or 1.9.x) – Zabba Nov 15 '10 at 06:26
  • 1
    @Chuck: Or even `[*1..52] + %w(A B)`. – Michael Kohl Nov 15 '10 at 07:35

1 Answers1

2

To make things simple, let deck be just ['A', 'B']. Here is step-by-step evaluation:

deck = ['A', 'B']
deck[deck.index("A")], deck[deck.index("B")] = deck[deck.index("B")], deck[deck.index("A")] # deck == ['A', 'B']
deck[deck.index("A")], deck[deck.index("B")] = deck[1], deck[0] # deck == ['A', 'B']
deck[deck.index("A")], deck[deck.index("B")] = 'B', 'A' # deck == ['A', 'B']
deck[0], deck[deck.index("B")] = 'B', 'A' # deck == ['A', 'B']
# Applying first assignment.
..., deck[deck.index("B")] = ..., 'A' # deck == ['B', 'B']
# NOTE: deck.index("B") is 0 now, not 1!
..., deck[0] = ..., 'A' # deck == ['B', 'B']
# Applying second assignment.
... # deck == ['A', 'B']

So what your code actually does is just assinging twise to the same element of array.

In order to fix this issue, just save deck.index() values to temporary arrays:

deck = []
(deck << (1..52).to_a << 'A' << 'B').flatten!
p deck
index_a, index_b = deck.index("A"), deck.index("B")
deck[index_a], deck[index_b] = deck[index_b], deck[index_a]
p deck

DNNX
  • 6,215
  • 2
  • 27
  • 33