Reputation: 23
I'm basically asking the exact same question as was asked here, but for Python 3.4.0.
In 3.4.0, this code:
a = ["Spears", "Adele", "NDubz", "Nicole", "Cristina"]
b = [1, 2, 3, 4, 5]
combined = zip(a, b)
random.shuffle(combined)
a[:], b[:] = zip(*combined)
does not work. What is the correct way to do this in 3.4.0?
Upvotes: 2
Views: 1623
Reputation: 304147
If memory was tight, you can write your own shuffle function to avoid the need to create the zipped list. The one from Python is not very complicated
def shuffle(self, x, random=None, int=int):
"""x, random=random.random -> shuffle list x in place; return None.
Optional arg random is a 0-argument function returning a random
float in [0.0, 1.0); by default, the standard random.random.
Do not supply the 'int' argument.
"""
randbelow = self._randbelow
for i in reversed(range(1, len(args[0]))):
# pick an element in x[:i+1] with which to exchange x[i]
j = randbelow(i+1) if random is None else int(random() * (i+1))
x[i], x[j] = x[j], x[i]
Your function could be this:
def shuffle2(a, b):
for i in reversed(range(1, len(a))):
j = int(random.random() * (i+1))
a[i], a[j] = a[j], a[i]
b[i], b[j] = b[j], b[i]
To shuffle an arbitrary number of lists in unison
def shuffle_many(*args):
for i in reversed(range(1, len(args[0]))):
j = int(random.random() * (i+1))
for x in args:
x[i], x[j] = x[j], x[i]
eg
>>> import random
>>> def shuffle_many(*args):
... for i in reversed(range(1, len(args[0]))):
... j = int(random.random() * (i+1))
... for x in args:
... x[i], x[j] = x[j], x[i]
...
>>> a = ["Spears", "Adele", "NDubz", "Nicole", "Cristina"]
>>> b = [1, 2, 3, 4, 5]
>>> shuffle_many(a, b)
>>> a
['Adele', 'Spears', 'Nicole', 'NDubz', 'Cristina']
>>> b
[2, 1, 4, 3, 5]
Upvotes: 2
Reputation: 25954
In python 3, zip
returns a zip
object (i.e. it's itertools.izip
from python 2).
You need to force it to materialize the list:
combined = list(zip(a, b))
Upvotes: 5
Reputation: 37319
In Python 3, zip
returns an iterator rather than a list, so cast it to a list before shuffling it:
combined = list(zip(a, b))
Upvotes: 0
Reputation: 7187
Change combined = zip(a,b)
to combined = list(zip(a,b))
. You need a list, not an iterator, in order to shuffle in place.
Upvotes: 0