簡體   English   中英

在列表的嵌套列表中洗牌特定元素

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM