randomizing two lists and maintaining order in python

Question:

Say I have two simple lists,

a = ['Spears', "Adele", "NDubz", "Nicole", "Cristina"]
b = [1,2,3,4,5]
len(a) == len(b)

What I would like to do is randomize a and b but maintain the order. So, something like:

a = ["Adele", 'Spears', "Nicole", "Cristina", "NDubz"]
b = [2,1,4,5,3]

I am aware that I can shuffle one list using:

import random
random.shuffle(a)

But this just randomizes a, whereas, I would like to randomize a, and maintain the “randomized order” in list b.

Would appreciate any guidance on how this can be achieved.

Asked By: JohnJ

||

Answers:

I’d combine the two lists together, shuffle that resulting list, then split them. This makes use of zip()

a = ["Spears", "Adele", "NDubz", "Nicole", "Cristina"]
b = [1, 2, 3, 4, 5]

combined = list(zip(a, b))
random.shuffle(combined)

a[:], b[:] = zip(*combined)
Answered By: Tim

Use zip which has the nice feature to work in ‘both’ ways.

import random

a = ['Spears', "Adele", "NDubz", "Nicole", "Cristina"]
b = [1,2,3,4,5]
z = zip(a, b)
# => [('Spears', 1), ('Adele', 2), ('NDubz', 3), ('Nicole', 4), ('Cristina', 5)]
random.shuffle(z)
a, b = zip(*z)
Answered By: user647772

Another way could be

a = ['Spears', "Adele", "NDubz", "Nicole", "Cristina"]
b = range(len(a)) # -> [0, 1, 2, 3, 4]
b_alternative = range(1, len(a) + 1) # -> [1, 2, 3, 4, 5]
random.shuffle(b)
a_shuffled = [a[i] for i in b] # or:
a_shuffled = [a[i - 1] for i in b_alternative]

It is the reverse approach, but could help you nevertheless.

Answered By: glglgl

Note that Tim’s answer only works in Python 2, not Python 3. If using Python 3, you need to do:

combined = list(zip(a, b))
random.shuffle(combined)
a[:], b[:] = zip(*combined)

otherwise you get the error:

TypeError: object of type 'zip' has no len()
Answered By: Adam_G

That’s my way:

import random
def shuffleTogether(A, B):
    if len(A) != len(B):
        raise Exception("Lengths don't match")
    indexes = range(len(A))
    random.shuffle(indexes)
    A_shuffled = [A[i] for i in indexes]    
    B_shuffled = [B[i] for i in indexes]
    return A_shuffled, B_shuffled

A = ['a', 'b', 'c', 'd']
B = ['1', '2', '3', '4']
A_shuffled, B_shuffled = shuffleTogether(A, B)
print A_shuffled
print B_shuffled
Answered By: Nathan B

To avoid Reinventing The Wheel use sklearn

from sklearn.utils import shuffle

a, b = shuffle(a, b)
Answered By: Nimrod Morag

There’s a simpler way that avoids zipping, copying and all of that heavy stuff. We can shuffle both of them separately, but using the same seed both times, which guarantees that the order of the shuffles will be the same.

import random as rd

A = list("abcde")
B = list(range(len(A)))
fixed_seed = rd.random()
rd.Random(fixed_seed).shuffle(A)
rd.Random(fixed_seed).shuffle(B)

A and B are then:

['e', 'a', 'c', 'b', 'd']
[ 4,   0,   2,   1,   3]

The more generic version, for an arbitrary number of lists:

def shuffle(*xss):
    seed = rd.random()
    for xs in xss:
        rd.Random(seed).shuffle(xs)
Answered By: Pig
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.