如何在Python中跨嵌套列表随机洗牌项目?

2024-04-28 22:21:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前正在做一个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']
                  ...]

Tags: 项目列表food时间食物dinnerperson1晚餐
2条回答

您可以将列表分成,然后将每列洗牌并重新组合

要将列作为列表获取,请使用^{} function,外部列表作为独立的参数应用,并使用*args语法zip()返回元组,但是如果我们想洗牌,我们需要列表,所以我使用map()来转换每个元组

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

因为每个都作为参数传入,zip()将每行的第一个值配对为一个元组,将下一行配对为另一个元组,以此类推

现在您有三个单独的列表,每个列表都可以传递给^{}

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']]

如果您只想将第一个列洗牌,而将其他列作为一个整体洗牌(因此您最终将'personA'('foodB', 'dinner timeB')配对),然后我会先洗牌外部列表或其副本,然后分离出people列进行洗牌和重新组合。为了避免复制,您可以使用^{}从输入序列中随机抽样,只需恰好具有相同的长度。这恰好与使用^{得到相同的结果,但无需先复制输入序列并在适当的位置进行洗牌:

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']]

我使用了另一个“技巧”,我们在赋值中使用*other,将zip(...)的第一个结果赋值给people,并将其他所有结果赋值给other

否则,如果有数量可变的列都需要单独洗牌,只需在zip(*food)上使用一个循环,并将每个洗牌列附加到columns列表中,这样就可以再次将这些列与zip(*columns)重新组合

可轻松组合成一个函数:

import random

def shuffle_columns(list_of_rows):
    columns = []
    for column in zip(*list_of_rows):
        # shuffled list of column values
        shuffled = random.sample(column, len(column))
        columns.append(shuffled)
    return [list(row) for row in zip(*columns)]

如果要相对于其他列洗牌第一列,可以提取并重新分配它:

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

如果需要对整个内容进行洗牌,则可以在第一列相对于其他列进行洗牌后执行此操作:

random.shuffle(people)

如果要按人排序,也可以这样做:

people.sort()

相关问题 更多 >