y3trgfhsfgr
y3trgfhsfgr

Reputation: 467

Shuffling two lists separately in Python

here is my code:

import random
from random import shuffle

a = ['a','b','c','d']
b = ['a','b','c','d']
c = ['w','x','y','z']
d = ['w','x','y','z']
indices = random.sample(range(len(a)), len(a))
a = map(a.__getitem__, indices)
b = map(b.__getitem__, indices)
shuffle(c)
shuffle(d)
print a,b,c,d

What this code does is it shuffles a and b in the same order, and shuffles c and d in their own order. What I am trying to do now is making two longer lists composed of a and c, and b and d, and put them in a randomized order. What I want though is for a and b stay the same order across lists. Is there any way to do this? Any help will be greatly appreciated. :)

Edit:

I would like the output to look something like this, where lists a&b correspond and c&d are just randomized independently.

['d','x','w','b','a','y','c','z']

['d','z','y','b','a','x','c','w']

Upvotes: 1

Views: 534

Answers (3)

Simon
Simon

Reputation: 10841

If we shuffle c and d first, randomly sampling from the concatenated lists ac and bd gives the required result (I'm using Python 3 so the printing requires parentheses):

import random
from random import shuffle

a = ['a','b','c','d']
b = ['a','b','c','d']
c = ['w','x','y','z']
d = ['w','x','y','z']
shuffle(c)
shuffle(d)
# print a,b,c,d
print (a,b,c,d)
ac = a + c
bd = b + d
indices = random.sample(range(len(ac)),len(ac))
ac = list(map(ac.__getitem__, indices))
bd = list(map(bd.__getitem__, indices))
#print ac, bd
print (ac, bd)

Output as follows:

['a', 'b', 'c', 'd'] ['a', 'b', 'c', 'd'] ['x', 'w', 'z', 'y']['y', 'z', 'w', 'x']
['y', 'z', 'c', 'x', 'b', 'w', 'd', 'a'] ['x', 'w', 'c', 'y', 'b', 'z', 'd', 'a']

EDIT:

Thanks to @Jan-Philip Gehrcke who points out that using numpy indexing (as follows) is much faster when the lists are large:

from random import shuffle
import numpy as np

a = ['a','b','c','d']
b = a[:]
c = ['w','x','y','z']
d = c[:]
shuffle(c)
shuffle(d)
# print a,b,c,d
print (a,b,c,d)
ac = np.array(a + c)
bd = np.array(b + d)
indices = list(range(len(ac)))
shuffle(indices)
ac = ac[indices]
bd = bd[indices]
#print ac, bd
print (ac, bd)

Upvotes: 3

BrenBarn
BrenBarn

Reputation: 251373

Here is one approach:

a = ['a','b','c','d']
# make b later
c = ['w','x','y','z']
d = ['w','x','y','z']
random.shuffle(a)
random.shuffle(c)
random.shuffle(d)
b = list(a)

x = a + c
random.shuffle(x)

y = []
for item in x:
    if item in a:
        y.append(b.pop())
    else:
        y.append(d.pop())

>>> x
['w', 'z', 'b', 'x', 'c', 'd', 'a', 'y']
>>> y
['z', 'y', 'b', 'x', 'c', 'd', 'a', 'w']

If you want a and b to be in the same random order, it's more convenient to just shuffle a, and then make b a copy of it. Then to make the new lists x and y, I first make x by shuffling a + c, and then build up y by going through x and adding a member from b or d depending on whether the corresponding element of x is in a or c.

This approach assumes that the set of elements in a and b is disjoint from those in c and d. The current version also destroys b and d in the process of making y, although this could be fixed with a slightly more cumbersome algorithm (keeping track of an index into b and d and grabbing elements by index instead of popping).

Upvotes: 1

Amrita Sawant
Amrita Sawant

Reputation: 10913

how about random shuffling c first and then zipping to a ?

    import random
    a=['a','b','c','d']
    b=['a','b','c','d']
    c=['w','x','y','z']
    d=['w','x','y','z']
    random.shuffle(c)
    a_c = zip(a,c)
    print a_c

[('a', 'y'), ('b', 'z'), ('c', 'x'), ('d', 'w')]

The order of list a is not changed while list c is shuffled randomly. Hope it helps.

Upvotes: 0

Related Questions