簡體   English   中英

如何在python中有效地刪除循環中的列表元素

[英]How to remove list elements within a loop effectively in python

我有一個代碼如下。

for item in my_list:
        print(item[0])
        temp = []
        current_index = my_list.index(item)
        garbage_list = creategarbageterms(item[0])

        for ele in my_list:
            if my_list.index(ele) != current_index:
                for garbage_word in garbage_list:
                    if garbage_word in ele:
                        print("concepts: ", item, ele)
                        temp.append(ele)
        print(temp)

現在,我想在它被附加到temp時從mylist刪除ele (因此,它不會在主循環中被處理,因為它是一個垃圾字)。

我知道,當它處於循環中時,從列表中直接刪除元素是不好的。 因此,我有興趣知道是否有任何有效的方法來做到這一點?

例如,如果mylist如下;

    mylist = [["tim_tam", 879.3000000000001], ["yummy_tim_tam", 315.0], ["pudding", 298.2], 
["chocolate_pudding", 218.4], ["biscuits", 178.20000000000002], ["berry_tim_tam", 171.9], 
["tiramusu", 158.4], ["ice_cream", 141.6], ["vanilla_ice_cream", 122.39999999999999]]

第一次迭代

對於第一個元素tim_tam ,我得到了諸如yummy_tim_tamberry_tim_tam類的垃圾字。 所以他們會被添加到我的temp列表中。

現在我想從列表中刪除yummy_tim_tamberry_tim_tam (因為它們已經添加到temp ),因此它不會從頭開始執行。

第二次迭代

現在,由於yummy_tim_tam不再在列表中,這將執行pudding 對於pudding我得到了一組不同的垃圾詞,如chocolate_puddingbiscuitstiramu 因此,它們將被添加到temp並將被刪除。

第3次迭代

ice_cream將被選中。 這個過程將繼續下去。

我的最終目標是獲得如下三個單獨的列表。

["tim_tam", 879.3000000000001], ["yummy_tim_tam", 315.0], ["berry_tim_tam", 171.9] , ["pudding", 298.2]

["chocolate_pudding", 218.4], ["biscuits", 178.20000000000002], ["tiramusu", 158.4]

["ice_cream", 141.6], ["vanilla_ice_cream", 122.39999999999999]

此代碼生成您想要的內容:

my_list = [['tim_tam', 879.3], ['yummy_tim_tam', 315.0], ['pudding', 298.2],
           ['chocolate_pudding', 218.4], ['biscuits', 178.2], ['berry_tim_tam', 171.9],
           ['tiramusu', 158.4], ['ice_cream', 141.6], ['vanilla_ice_cream', 122.39]
           ]

creategarbageterms = {'tim_tam' : ['tim_tam','yummy_tim_tam', 'berry_tim_tam'],
                      'pudding': ['pudding', 'chocolate_pudding', 'biscuits', 'tiramusu'],
                      'ice_cream': ['ice_cream', 'vanilla_ice_cream']}

all_data = {}
temp = []
for idx1, item in enumerate(my_list):
    if item[0] in temp: continue
    all_data[idx1] = [item]

    garbage_list = creategarbageterms[item[0]]

    for idx2, ele in enumerate(my_list):
        if idx1 != idx2:
            for garbage_word in garbage_list:
                if garbage_word in ele:
                    temp.append(ele[0])
                    all_data[idx1].append(ele)

for item in all_data.values():
    print('-', item)  

這會產生:

- [['tim_tam', 879.3], ['yummy_tim_tam', 315.0], ['berry_tim_tam', 171.9]]
- [['pudding', 298.2], ['chocolate_pudding', 218.4], ['biscuits', 178.2], ['tiramusu', 158.4]]
- [['ice_cream', 141.6], ['vanilla_ice_cream', 122.39]]  

請注意,出於示例的目的,我創建了一個模擬creategarbageterms函數(作為字典),它生成您在帖子中定義的術語列表。 請注意使用defaultdict,它允許無限次迭代,即生成的無限數量的最終列表。

我建議這樣做:

mylist = [["tim_tam", 879.3000000000001],   
          ["yummy_tim_tam", 315.0],
          ["pudding", 298.2], 
          ["chocolate_pudding", 218.4], 
          ["biscuits", 178.20000000000002],
          ["berry_tim_tam", 171.9], 
          ["tiramusu", 158.4], 
          ["ice_cream", 141.6], 
          ["vanilla_ice_cream", 122.39999999999999]]

d = set()   # remembers unique keys, first one in wins

for i in mylist:
    shouldAdd = True
    for key in d:
        if i[0].find(key) != -1:    # if this key is part of any key in the set
            shouldAdd = False       # do not add it

    if not d or shouldAdd:          # empty set or unique: add to set
        d.add(i[0]) 

myCleanList = [x for x in mylist if x[0] in d]    # clean list to use only keys in set

print(myCleanList)

輸出:

[['tim_tam', 879.3000000000001], 
 ['pudding', 298.2], 
 ['biscuits', 178.20000000000002], 
 ['tiramusu', 158.4], 
 ['ice_cream', 141.6]]

如果列表中的事物順序不重要,您可以直接使用字典 - 並從字典中創建列表。

如果您需要子列表,請創建它們:

similarThings = [ [x for x in mylist if x[0].find(y) != -1] for y in d]

print(similarThings)

輸出:

[
    [['tim_tam', 879.3000000000001], ['yummy_tim_tam', 315.0], ['berry_tim_tam', 171.9]], 
    [['tiramusu', 158.4]], 
    [['ice_cream', 141.6], ['vanilla_ice_cream', 122.39999999999999]], 
    [['pudding', 298.2], ['chocolate_pudding', 218.4]], 
    [['biscuits', 178.20000000000002]]
]

正如@joaquin在評論中所指出的那樣,我錯過了將tiramusubiscuitspudding分組的creategarbageterms()函數以適應100%的問題 - 我的回答是提倡“不要在交互中修改列表,使用適當的集合或字典過濾它這里的唯一鍵是不是后面提到的鍵的一部分的鍵。

你想要一個循環遍歷列表的外循環,以及一個可以修改同一個列表的內循環。

我看到你在評論中得到的建議根本就是根本不刪除內部循環中的條目,而是檢查術語是否已經處於temp 這是可能的,並且可能更容易閱讀,但不一定是關於處理時間的最佳解決方案。

我也看到你收到了Patrick使用字典的答案。 對於您的特定用例,這可能是最干凈的解決方案,但是沒有解決標題中更一般的問題,即在循環中刪除列表中的項目時。 如果出於某種原因這是非常必要的,我建議如下:

idx = 0
while idx < len(my_list)
    item = my_list[idx]
    print(item[0])
    temp = []
    garbage_list = creategarbageterms(item[0])

    ele_idx = 0
    while ele_idx < len(my_list):
        if ele_idx != idx:
            ele = my_list[ele_idx]
            for garbage_word in garbage_list:
                if garbage_word in ele:
                    print("concepts: ", item, ele)
                    temp.append(ele)
                    del my_list[ele_idx]
        ele_idx += 1
    print(temp)
    idx += 1

這里的關鍵見解是,通過使用while循環而不是for循環,您可以對程序的控制流程進行更詳細的“手動”控制,並且更安全地執行“非常規”的事情。環。 我只建議這樣做,如果你真的不得不出於任何原因。 這個解決方案更接近您提出的字面問題,更接近您原來自己的代碼,但可能不是最簡單的讀取/大多數Pythonic代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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