在 Python 中打乱子列表组

Rod*_*phe 2 python

我想改组这个列表:

[[1, 'A'], [2, 'A'], [6, 'B'], [3, 'B'], [4, 'C'], [5, 'C'], [7, 'F']]
Run Code Online (Sandbox Code Playgroud)

但是我需要由子列表第二个元素标识的组保持在一起,以便无序列表看起来像这样:

[[6, 'B'], [3, 'B'], [7, 'F'], [1, 'A'], [2, 'A'], [4, 'C'], [5, 'C']]
Run Code Online (Sandbox Code Playgroud)

所有“B”、“F”、“A”和“C”子列表都放在一起的地方。

我猜测使用 shuffle 和 groupby 的组合可以解决问题,但我不知道从哪里开始。任何想法将不胜感激!

Ste*_*ann 5

items = [[1, 'A'], [2, 'A'], [6, 'B'], [3, 'B'], [4, 'C'], [5, 'C'], [7, 'F']]

import itertools, operator, random

groups = [list(g) for _, g in itertools.groupby(items, operator.itemgetter(1))]
random.shuffle(groups)
shuffled = [item for group in groups for item in group]

print(shuffled)
Run Code Online (Sandbox Code Playgroud)

打印例如:

[[4, 'C'], [5, 'C'], [1, 'A'], [2, 'A'], [7, 'F'], [6, 'B'], [3, 'B']]
Run Code Online (Sandbox Code Playgroud)


Ste*_*ann 5

给每个组一个随机数并以此排序。子列表保持在一起是因为 Python 的排序是稳定的。


多年后更新:使用defaultdict看起来更好,并且只为每组生成一个随机数,而不是为每个元素生成一个:

from random import random
from collections import defaultdict

r = defaultdict(random)
items.sort(key=lambda item: r[item[1]])
Run Code Online (Sandbox Code Playgroud)

作为挤压oneliner:

items.sort(key=lambda i, r=defaultdict(random): r[i[1]])
Run Code Online (Sandbox Code Playgroud)

回到原来的答案:


items = [[1, 'A'], [2, 'A'], [6, 'B'], [3, 'B'], [4, 'C'], [5, 'C'], [7, 'F']]

import random

r = {b: random.random() for a, b in items}
items.sort(key=lambda item: r[item[1]])

print(items)
Run Code Online (Sandbox Code Playgroud)

打印例如:

[[6, 'B'], [3, 'B'], [4, 'C'], [5, 'C'], [7, 'F'], [1, 'A'], [2, 'A']]
Run Code Online (Sandbox Code Playgroud)

这两行可以合并,然后你就没有那个额外的变量在后面飞来飞去。

items.sort(key=lambda item, r={b: random.random() for a, b in items}: r[item[1]])
Run Code Online (Sandbox Code Playgroud)