简体   繁体   中英

randomizing two lists and maintaining order in python

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.

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)

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)

To avoid Reinventing The Wheel use sklearn

from sklearn.utils import shuffle

a, b = shuffle(a, b)

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()

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)

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM