簡體   English   中英

從python中的列表列表中刪除相似但不相同的列表

[英]Removing similar, but not identical, lists from a list of lists in python

我正在確定方向圖中的循環。 我的函數返回一個列表列表,該列表將節點存儲在找到的任何循環中。

例如在圖中這樣連接節點的圖中:

(1,2)(2,3)(3,4)(3,5)(5,2)

在2-3-5找到一個循環,因此該函數將返回:

[[2,3,5]]

在某些情況下,有多個循環會返回類似以下內容的內容:

[[2,3,4][6,7,8,9]]

很好,但是如果圖形中有多個起點,它們在不同點處連接同一循環,例如圖形中:

(1,2)(2,3)(3,4)(3,5)(5,2)(6,3)

節點1和6都在不同點處加入同一循環,並返回:

[[2,3,5][3,5,2]]

因此,這里有兩個相同的循環,它們不是相同的列表。 我想識別這樣的重復項,並刪除所有重復項(哪一個無關緊要)。

請注意,在某些情況下,可能存在多個循環,一個循環是重復的,例如:

[[2,3,5][3,5,2][7,8,9,6]]

我試着調查itertools:

loops.sort()
list(loops for loops,_ in itertools.groupby(loops))

但這無濟於事,而且我也不能100%地確定這樣做是否合適。 有任何想法嗎? 我在python 2.4上。 謝謝你的幫助。

如果您只關心每個循環的元素而不是順序,那么我將通過對每個循環進行排序來規范化每個循環,然后采用集合:

>>> loops = [[2,3,5],[3,5,2],[7,8,9,6]]
>>> set(tuple(sorted(loop)) for loop in loops)
set([(2, 3, 5), (6, 7, 8, 9)])

為了在這里使用set ,您需要轉換為元組。 您可以將元組轉換回列表,或者將最終集合轉換回列表(甚至可以使用sorted以獲得規范順序),但是您是否實際需要取決於您要對其進行處理。

如果您需要保留路徑順序,我可以采用其他方式規范化:

def rotated(l, n):
    return l[n:] + l[:n]

def canonicalize(l):
    m = min(l)
    where = l.index(m)
    return rotated(l, where)

接着

>>> loops = [[2,5,3], [5,3,2], [7,8,6,9]]
>>> set(tuple(canonicalize(loop)) for loop in loops)
set([(2, 5, 3), (6, 9, 7, 8)])

[編輯:請注意,只有在路徑中每個頂點只能訪問一次時,這種簡單的規范化才有效。

首先,您需要定義相似之處,因為它比set強:

def is_similar(X,Y):
    n = len(X)
    return len(Y) == n and any( all( X[i] == Y[(i+j)%n] 
                                     for i in range(n) )
                                for j in range(1,n) ) #the 1 here so that identical lists are not similar

這種區別很重要,因為路徑(1,2,3,4)是從路徑(1,3,2,4) 不同 ,它們不對應於同一個循環。

def remove_similars(L):
     new_L = []
     for item in L:
         if not any( is_similar(item, l) for l in new_L ):
             new_L.append(item)
     return new_L

您可以選擇每個列表中的一set 如果兩組相等,則您有一個重復的循環。 您雖然失去了循環中節點的順序,但這對您來說重要嗎?

暫無
暫無

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

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