如何在Python的嵌套列表中随机调整项目?

时间:2020-01-16 15:47:25

标签: python list shuffle

我目前正在做一个uni项目,该项目需要我随机排列嵌套列表中的项目。

假设我有一个嵌套列表,其中包含一个人的姓名,他们吃晚餐的食物以及他们吃晚餐的时间,看起来像这样:

food = [['person1', 'food1', 'dinner time1'],
        ['person2', 'food2', 'dinner time2'], 
        ['person3', 'food3', 'dinner time3'],
        ...]

有没有一种方法可以随机地重新排列列表,以便每个人有不同的食物和晚餐时间,如下所示:

food_reshuffle = [['person2', 'food3', 'dinner time3'],
                  ['person1', 'food2', 'dinner time2'],
                  ['person3', 'food1', 'dinner time1']
                  ...]

2 个答案:

答案 0 :(得分:3)

您可以将列表分成,然后将每列随机排列,然后重新组合。

要获取列为列表,请使用zip() function,将外部列表用作{em> separate 参数,并使用*args语法。 zip()返回元组,但是如果要改组,我们需要列表,所以我使用map()进行转换。

people, foods, dinner_times = map(list, zip(*food))

由于每个 row 作为参数传递,zip()将每一行的第一个值配对为一个元组,将下一行配对为另一个元组,等等。

现在您有三个单独的列表,每个列表都可以传递给random.shuffle()

import random

random.shuffle(people)
random.shuffle(foods)
random.shuffle(dinner_times)

然后再次与zip()重新组合:

food_reshuffle = [list(row) for row in zip(people, foods, dinner_times)]

演示:

>>> from pprint import pprint
>>> import random
>>> food = [['person1', 'food1', 'dinner time1'],
...         ['person2', 'food2', 'dinner time2'],
...         ['person3', 'food3', 'dinner time3'],
... ]
>>> people, foods, dinner_times = map(list, zip(*food))
>>> random.shuffle(people)
>>> random.shuffle(foods)
>>> random.shuffle(dinner_times)
>>> food_reshuffle = [list(row) for row in zip(people, foods, dinner_times)]
>>> pprint(food_reshuffle)
[['person2', 'food2', 'dinner time1'],
 ['person3', 'food3', 'dinner time2'],
 ['person1', 'food1', 'dinner time3']]

如果您只想改组 first 列,而将其他列改组为一个整体(因此您最终将'personA' pair 配对('foodB', 'dinner timeB'),然后我先将外部列表或它们的副本 进行混洗,然后将人员列分开进行混排和重组。为避免产生副本,可以使用{ {3}}从输入序列中随机取样,只是发生的长度相同,碰巧得到与使用random.shuffle()相同的结果,但无需复制首先输入序列,然后就位洗牌:

import random

shuffled = random.sample(food, len(food))
people, *other = zip(*shuffled)
food_reshuffle = [[p, *o] for p, o in zip(random.sample(people, len(people), *other)]

具有以下结果:

>>> shuffled = random.sample(food, len(food))
>>> people, *other = zip(*shuffled)
>>> food_reshuffle = [list(row) for row in zip(random.sample(people, len(people)), *other)]
>>> pprint(food_reshuffle)
[['person2', 'food2', 'dinner time2'],
 ['person1', 'food3', 'dinner time3'],
 ['person3', 'food1', 'dinner time1']]

我使用了另一个“技巧”,其中我们使用{{1}将zip(...)的第一个结果分配给people,将其他所有内容分配给other }。

否则,如果您有可变数量的列,都需要独立进行改组,则只需在*other上循环,然后将每个改组后的列附加到zip(*food)列表中,然后可以重新组合它们与columns

很容易组合成一个函数

zip(*columns)

答案 1 :(得分:0)

如果您只想相对于其他第一列进行洗牌,则可以提取并重新分配它:

rails console

如果您需要对整个列进行改组,则可以在第一列相对于其他列进行改组后再执行以下操作:

first = [entry[0] for entry in people]
random.shuffle(first)
for entry, person in zip(people,  first):
    entry[0] = person

如果要按人排序,也可以执行以下操作:

random.shuffle(people)