<p>您可以将列表分成<em>列</em>,然后将每列洗牌并重新组合</p>
<p>要将列作为列表获取,请使用<a href="https://docs.python.org/3/library/functions.html#zip" rel="nofollow noreferrer">^{<cd1>} function</a>,外部列表作为独立的</em>参数应用,并使用<code>*args</code>语法<code>zip()</code>返回元组,但是如果我们想洗牌,我们需要列表,所以我使用<code>map()</code>来转换每个元组</p>
<pre><code>people, foods, dinner_times = map(list, zip(*food))
</code></pre>
<p>因为每个<em>行</em>都作为参数传入,<code>zip()</code>将每行的第一个值配对为一个元组,将下一行配对为另一个元组,以此类推</p>
<p>现在您有三个单独的列表,每个列表都可以传递给<a href="https://docs.python.org/3/library/random.html#random.shuffle" rel="nofollow noreferrer">^{<cd6>}</a>:</p>
<pre><code>import random
random.shuffle(people)
random.shuffle(foods)
random.shuffle(dinner_times)
</code></pre>
<p>然后再次与<code>zip()</code>重新组合:</p>
<pre><code>food_reshuffle = [list(row) for row in zip(people, foods, dinner_times)]
</code></pre>
<p>演示:</p>
<pre><code>>>> 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']]
</code></pre>
<p>如果您只想将<em>第一个</em>列洗牌,而将其他列作为一个整体洗牌(因此您最终将<code>'personA'</code>与<em>对</em><code>('foodB', 'dinner timeB')</code>配对),然后我会先洗牌外部列表或其副本<em>,然后分离出people列进行洗牌和重新组合。为了避免复制,您可以使用<a href="https://docs.python.org/3/library/random.html#random.sample" rel="nofollow noreferrer">^{<cd10>}</a>从输入序列中随机抽样,只需<em>恰好</em>具有相同的长度。这恰好与使用^{<cd6>得到相同的结果,但无需先复制输入序列并在适当的位置进行洗牌:</p>
<pre><code>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)]
</code></pre>
<p>其结果是:</p>
<pre><code>>>> 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']]
</code></pre>
<p>我使用了另一个“技巧”,我们在赋值中使用<code>*other</code>,将<code>zip(...)</code>的第一个结果赋值给<code>people</code>,并将其他所有结果赋值给<code>other</code></p>
<p>否则,如果有数量可变的列都需要单独洗牌,只需在<code>zip(*food)</code>上使用一个循环,并将每个洗牌列附加到<code>columns</code>列表中,这样就可以再次将这些列与<code>zip(*columns)</code>重新组合</p>
<p>可轻松组合成一个函数:</p>
<pre><code>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)]
</code></pre>