Is there a way to shuffle pairs within a list?

I have a pairs of names in a list that I want to shuffle for xgboost.

Input: [['A1', 'B1'], ['A2', 'B2'], ['A3', 'B3'], ['A4', 'B4'], ['A5', 'B5'], ['A6', 'B6'], ['A7', 'B7'], ['A8', 'B8']]

Expecting: [['A1', 'B1'], ['B2', 'A2'], ['A3', 'B3'], ['A4', 'B4'], ['B5', 'A5'], ['A6', 'B6'], ['A7', 'B7'], ['B8', 'A8']]

I have tried this and it does produce the results I want but I believe there’s an easy way.:

rand_number = random.randint(0, 1000)
tlist_rand = []
for t in tlist:
    if rand_number % 3 == 0:
        tlist_rand.append(random.sample(t, len(t)))
        rand_number = random.randint(0, 1000)
    else:
        tlist_rand.append(t)
        rand_number = random.randint(0, 1000)

Input: [['A1', 'B1'], ['A2', 'B2'], ['A3', 'B3'], ['A4', 'B4'], ['A5', 'B5'], ['A6', 'B6'], ['A7', 'B7'], ['A8', 'B8']]

The rand tuple is: [['A1', 'B1'], ['A2', 'B2'], ['A3', 'B3'], ['B4', 'A4'], ['A5', 'B5'], ['A6', 'B6'], ['A7', 'B7'], ['A8', 'B8']]

You can simplify your code a lot:

  1. Since the elements are pairs, you don’t need to shuffle them, only reverse them. But because it’s 1/2 that a pair gets shuffled, we’ll need to double the random number to keep the same odds.
  2. You don’t need to get rand_number in three different places, only one.

Also, there are 334 numbers divisible by 3 in [0, 1000], and 334/1001 is really close to 1/3, so might as well use the smaller number.

So ultimately I’ll use 1/6, implemented as k < 1, k in [0, 5].

tlist_rand = [t[::-1] if random.randrange(6) < 1 else t for t in tlist]

Example output:

[['A1', 'B1'], ['A2', 'B2'], ['B3', 'A3'], ['A4', 'B4'], ['B5', 'A5'], ['A6', 'B6'], ['A7', 'B7'], ['A8', 'B8']]

random.shuffle is the right tool for the job. But it mutates the list passed to it, so use it in a loop rather than a list comprehension.

>>> lst = [['A1', 'B1'], ['A2', 'B2'], ['A3', 'B3'], ['A4', 'B4'], ['A5', 'B5'], ['A6', 'B6'], ['A7', 'B7'], ['A8', 'B8']]
>>> import random
>>> for x in lst: random.shuffle(x)
...
>>> lst
[['A1', 'B1'], ['A2', 'B2'], ['B3', 'A3'], ['B4', 'A4'], ['B5', 'A5'], ['B6', 'A6'], ['A7', 'B7'], ['B8', 'A8']]

If you need a new list you need to make a deep copy of the original list, and then you can shuffle that.

>>> import copy
>>> lst2 = copy.deepcopy(lst)
>>> for x in lst2: random.shuffle(x)
...
>>> lst2
[['B1', 'A1'], ['B2', 'A2'], ['B3', 'A3'], ['A4', 'B4'], ['B5', 'A5'], ['A6', 'B6'], ['B7', 'A7'], ['B8', 'A8']]
>>> lst
[['A1', 'B1'], ['A2', 'B2'], ['B3', 'A3'], ['B4', 'A4'], ['B5', 'A5'], ['B6', 'A6'], ['A7', 'B7'], ['B8', 'A8']]

You can use random.shuffle, this function can shuffle list inplace.

Looks like you want a 1 in 3 chance of swapping the two elements of each sub-list.

In which case you could do it like this:

from random import randint

data = [['A1', 'B1'], ['A2', 'B2'], ['A3', 'B3'], ['A4', 'B4'], ['A5', 'B5'], ['A6', 'B6'], ['A7', 'B7'], ['A8', 'B8']]

for e in data:
    if randint(0, 2) == 0:
        e[0], e[1] = e[1], e[0]

Leave a Comment