[英]Shuffling specific element within a nested list of lists
我正在嘗試隨機打亂嵌套列表中的一個元素。
例如我有:
list1=[[['a', 'b', 'c', 1], ['a', 'b', 'c', 2]], [['a', 'b', 'c', 3], ['a', 'b', 'c', 4]], [['a', 'b', 'c', 5], ['a', 'b', 'c', 6]]]
我想隨機打亂每個子列表的第三個元素(浮動),同時保持列表條目的 rest 及其在這個嵌套列表中的結構完好無損。 例如:
list1=[[['a', 'b', 'c', 1], ['a', 'b', 'c', 6]], [['a', 'b', 'c', 4], ['a', 'b', 'c', 2]], [['a', 'b', 'c', 3], ['a', 'b', 'c', 5]]]
到目前為止,我想出了以下幾點:
import random
list1 = [[['a', 'b', 'c', 1], ['a', 'b', 'c', 2]], [['a', 'b', 'c', 3], ['a', 'b', 'c', 4]], [['a', 'b', 'c', 5], ['a', 'b', 'c', 6]]]
vals = [x[3] for line in list1 for x in line]
shuffled_vals = random.sample(vals,len(vals))
counter = 0
for i in range(len(list1)):
for j in range(len(list1[i])):
list1[i][j][3] = shuffled_vals[counter]
counter += 1
盡管這可以作為預期的工作,但我很好奇是否有更優雅/ Pythonic的解決方案。 另外,我不確定它的擴展性如何——我打算使用它的列表將包含數百萬個條目。
非常感謝任何改進此代碼(更 Pythonic 或更高效)的技巧。
你的代碼對我來說看起來不錯。 我會做幾乎相同的事情,除了我不會改變(就地修改)輸入列表。 通常你也會避免使用range(len(X))
並且更喜歡直接迭代X
的元素。
把它放在一起會得到這樣的東西:
from random import sample
vals = [x[3] for line in list1 for x in line]
vals = sample(vals, len(vals))
new_list = [[sub_l[:3] + [vals.pop()] for sub_l in l] for l in list1]
在這里,我還使用了.pop()
,因為我們可以在使用完vals
后立即將其丟棄。 這使我免於使用您擁有的counter
之類的東西。
也許一個小的改進是使用突變,我們可以完美地控制 object。 如果您想避免突變,使用random.sample()
非常方便,但如果您不在乎,可以簡單地將vals = sample(vals, len(vals))
替換為random.shuffle(vals)
。 我覺得這里更好一些,因為它更具可讀性。
使用迭代器可能會有所幫助:
import random
list1=[[['a', 'b', 'c', 1], ['a', 'b', 'c', 2]], [['a', 'b', 'c', 3], ['a', 'b', 'c', 4]], [['a', 'b', 'c', 5], ['a', 'b', 'c', 6]]]
mix = iter(random.sample([i[3] for j in list1 for i in j], len([i[3] for j in list1 for i in j])))
for i, v in enumerate(list1):
for j, w in enumerate(v):
list1[i][j][3] = next(mix)
print(list1)
[[['a', 'b', 'c', 5], ['a', 'b', 'c', 6]], [['a', 'b', 'c', 3], ['a', 'b', 'c', 2]], [['a', 'b', 'c', 1], ['a', 'b', 'c', 4]]]
或作為 function:
def shuffle_third(input_list):
current_third = [i[3] for j in input_list for i in j]
mix = iter(random.sample(current_third, len(current_third)))
for i, v in enumerate(input_list):
for j, w in enumerate(v):
input_list[i][j][3] = next(mix)
return input_list
我沒有設法獲得列表的遞歸替換,但這里有一個遞歸 function 將向下搜索,直到找到一個列表並返回指定 position 中的所有元素:
def any_pos_recursive(input_list, pos=0):
def recurse(next_layer, insert=False):
if type(next_layer[0]) is list:
for i in next_layer: recurse(i)
elif not insert: shuffle_list.append(next_layer[pos])
shuffle_list = []
recurse(input_list)
shuffle_iter = iter(random.sample(shuffle_list, len(shuffle_list)))
print(shuffle_list)
any_pos_recursive(list1)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.