簡體   English   中英

Python:刪除列表中至少由同一列表中的一個其他字符串包含的字符串

[英]Python: Remove Strings in a List that are contained by at least one other String in the same List

我想通過以下方式過濾我的字符串列表:如果同一列表中至少有一個其他字符串“”它我想排除 strings 或以不同的方式把這個:我想保持的字符串,如果是它的同一列表的任何其他字符串。 如果可能,區分大小寫應該在這里發揮作用。

為了更清楚地說明這一點,請在下面找到一個示例

我的“第一個”列表包含每個字符串:

elements =["tree","TREE","treeforest","water","waterfall"]

應用解決方案后,我很想收到此列表:

elements = ["tree","TREE","water"]

例如: treetreeforest 因此, treeforest被排除在我的列表之外。 同樣適用於waterwaterfall 但是,應該維護treeTREEwater ,因為沒有其他字符串“”它們。

由於我想將此應用於“更大”的字符串列表,因此首選更有效的解決方案。

希望這是可以理解的。 非常感謝提前! 任何幫助都受到高度贊賞。

相當優化的函數,帶有 2 個循環,節省了大量的循環迭代:

def filterlist(l):
    # keep track of elements, which will be deleted
    deletelist = [False for _ in l]

    for i, el in enumerate(l):
        # already in deletelist, jump right to the next el
        if deletelist[i]:
            continue

        for j, el2 in enumerate(l):
            # comparing item to itself or el2 already in deletelist?
            # jump to next el2
            if i == j or deletelist[j]:
                continue

            # the comparison everyone expects
            if el in el2:
                deletelist[j] = True

            # also, check the other way around
            # will save loop iterations later
            elif el2 in el:
                deletelist[i] = True
                break # causes jump to next el

    # create new list, keep elements that are not in deletelist
    return [el for i, el in enumerate(l) if not deletelist[i]]

通常內置函數更快,所以讓我們將其與 Ed Ward 的解決方案進行比較:

# result of Ed Ward's solution using timeit:
100000 loops, best of 10: 5.38 usec per loop

# filterlist function with loops using timeit:
100000 loops, best of 10: 4.42 usec per loop

有趣,但要獲得真正具有代表性的結果,您應該使用更大的元素列表運行 timeit。

from copy import deepcopy

def remove_composite_words(e,elements):
  temp = [x for x in elements if e in x]
  temp = set(temp)
  elements = list(set(elements).difference(temp))
  return e,sorted(elements, key=len)

def keep_shortest_root(elements):
  elements = deepcopy(elements)
  elements = list(set(elements))
  elements = sorted(elements, key=len)
  if len(elements[0]) ==0:
    elements = elements[1:]

  results = []
  e = elements[0]
  while elements:
    e,elements = remove_composite_words(e,elements)
    results.append(e)
    if elements:
      e = elements[0]

  return results
  
elements =["tree","TREE","treeforest","water","waterfall",'forestTREE','tree']

keep_shortest_root(elements)  

這應該返回

['tree', 'TREE', 'water']

這個怎么運作:

函數remove_composite_words()測試一個元素是否包含在列表中的任何其他元素中,並只保存那些匹配的元素。 然后它從初始列表中刪除匹配的元素。

因此,如果您有元素'a'和列表['a','aa','b','c']該函數將返回'a'和列表['b','c']

keep_shortest_root()remove_composite_words() keep_shortest_root()應用於初始列表,然后應用於轉換后的列表(來自remove_composite_words()輸出),直到沒有更多單詞為止。

請注意, keep_shortest_root()首先從輸入列表中獲取唯一的單詞,然后按長度對它們進行排序。 這與remove_composite_words()從初始列表中刪除匹配單詞的事實相結合,使算法運行得更快,因為比較次數隨着迭代次數而下降。

為已經提供的解決方案找到了一些更簡單的解決方案,我想我可能會加入

 def Remove_Subset(List):
    ListCopy=List
    for Element1 in List:
        for Element2 in List:
            if (Element1 in Element2) and (Element1!= Element2):
                ListCopy.remove(Element2)
    return(ListCopy)
elements =["treeforest","tree","TREE","treeforest","water","waterfall","tree"]
print(Remove_Subset(elements))


>>> ['tree', 'TREE', 'water']

這是我在評論中給出的答案的解釋


我使用了這個代碼:

new_elements = list(filter(lambda item: not any(elem in item for elem in elements if elem != item), elements))

產生:

['tree', 'TREE', 'water']

我不知道你對 Python 生成器表達式和filter了解多少,所以我還是盡量解釋一下。

filter是一個 Python 內置函數,它需要一個函數來在提供的可迭代對象(例如列表等)中的每個項目上使用。 在我們的例子中,函數是這樣的:

lambda item: not any(elem in item for elem in elements if elem != item)

此函數從列表 ( item ) 中獲取一個項目,然后遍歷列表中的每個元素 ( for elem in elements ),並為每個元素 ( elem ) 檢查該元素是否在我們的字符串 ( item ) 中。 請注意, if elem != item ,它會跳到下一個元素,因為我們不想將它與自身進行比較。

函數any只是不斷迭代,直到返回的表達式為True ,或者到達結尾。 如果有任何匹配項, any返回True ,但要告訴filter刪除此項,我們需要返回False ,因此我們反轉any的輸出。

我們還通過filter我們的列表( elements ),並將結果從filter轉換為另一個list


注意:使用any而不是迭代每個其他項目的每個項目的好處是,在找到匹配項的情況下,我們不必迭代整個列表:此時any返回。 理論上,這可能比沒有break語句的兩個嵌套 for 循環更快。

暫無
暫無

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

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