如何在Python中跨嵌套列表随机洗牌项目?
我目前正在做一个uni项目,该项目要求我在嵌套列表中随机移动项目 假设我有一个嵌套列表,其中包含一个人的名字、他们晚餐吃的食物以及他们吃饭的时间,看起来像这样:如何在Python中跨嵌套列表随机洗牌项目?,python,list,shuffle,Python,List,Shuffle,我目前正在做一个uni项目,该项目要求我在嵌套列表中随机移动项目 假设我有一个嵌套列表,其中包含一个人的名字、他们晚餐吃的食物以及他们吃饭的时间,看起来像这样: food = [['person1', 'food1', 'dinner time1'], ['person2', 'food2', 'dinner time2'], ['person3', 'food3', 'dinner time3'], ...] food_reshuffle =
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']
...]
有没有一种方法可以让我随机地重新排列列表,这样每个人都会有不同的食物和晚餐时间,看起来像这样:
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']
...]
您可以将列表分离为列,然后洗牌每列并重新组合它们 要将列作为列表,请使用,并将外部列表作为单独的参数应用,同时使用
*args
语法zip()
返回元组,但是如果我们想洗牌,我们需要列表,所以我使用map()
来转换每个元组
people, foods, dinner_times = map(list, zip(*food))
因为每行都作为参数传入,zip()
将每行的第一个值配对为一个元组,下一行配对为另一个元组,以此类推
现在您有三个单独的列表,每个列表都可以传递到:
然后再次使用zip()
重新组合:
演示:
如果您只想洗牌第一列,而其他列则作为一个整体洗牌(因此您最终会得到'personA'
与该对('foodB','dinner timeB')配对)
,然后我会先洗牌外部列表或其副本,然后分离出people列进行洗牌和重新组合。为了避免复制,您可以使用从输入序列中随机取样,恰好长度相同。这恰好与使用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']]
我使用了另一个“技巧”,我们在作业中使用*other
将zip(…)
的第一个结果分配给people
,将其他所有结果分配给other
否则,如果有数量可变的列都需要单独洗牌,只需在zip(*food)
上使用一个循环,并将每个洗牌列附加到列
列表中,这样您就可以再次将这些列与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()
所以你真的有很多列,想把每一列都随机化吗?看起来就像是在洗牌第一列column@MartijnPieters是的,但我的数据存储在list@tyc_8991:正如Mad指出的,您的样本输出只随机分配了
(foodN,晚餐时间)
。这是预期的还是应该将foodN
和dinner\u timeN
列单独洗牌?其他列也洗牌,但似乎是作为一个单元一起洗牌。@MartijnPieters。这也很简单。无论哪种方式,最后都会进行两次洗牌。
people.sort()