2010-03-29 75 views
4

我想比較不等長的嵌套列表。我只對每個子列表的第一個元素之間的匹配感興趣。如果存在匹配,我希望將該匹配添加到另一個列表中,以便隨後轉換爲製表符分隔的文件。以下是我與工作的一個例子:Python - 比較嵌套列表並將匹配追加到新列表中?

x = [['1', 'a', 'b'], ['2', 'c', 'd']] 

y = [['1', 'z', 'x'], ['4', 'z', 'x']] 

match = [] 

def find_match(): 
    for i in x: 
     for j in y: 
      if i[0] == j[0]: 
       match.append(j) 
      return match 

這將返回:

[['1', 'x'], ['1', 'y'], ['1', 'x'], ['1', 'y'], ['1', 'z', 'x']] 

難道是重新處理列表中刪除重複很好的做法或可在此更簡單的方式完成?

而且,是它更好地使用元組的元組和/或元組進行比較的目的是什麼?

任何幫助,非常感謝。

問候, Seafoid。

+2

你是如何得到上述輸出的?我只得到以下元素[['1','z','x']]作爲輸出。 – naivnomore 2010-03-29 15:00:29

回答

6
  • 使用裝置獲得的不重複的集合。

    • 您必須使用元組而不是列表作爲項目,因爲設置的項目必須是可哈希的。
  • 您發佈的代碼似乎沒有生成您發佈的輸出。我不知道你應該如何從該輸入中生成輸出。例如,輸出有'y',輸入不是。

  • 我認爲你的功能的設計可以大大改善。目前,您將xymatch定義爲模塊級別,並明確讀取和變更它們。這不是你想要設計函數的方式 - 作爲一般規則,函數不應該在全局級別上改變某些東西。它應該明確地傳遞它所需的一切,並返回一個結果,而不是隱式地接收信息並改變它自身之外的東西。

    我會改變

    x = some list 
    y = some list 
    match = [] 
    def find_match(): 
        for i in x: 
         for j in y: 
          if i[0] == j[0]: 
           match.append(j) 
        return match # This is the only line I changed. I think you meant 
           # your return to be over here? 
    find_match() 
    

    x = some list 
    y = some list 
    
    def find_match(x, y): 
        match = [] 
        for i in x: 
         for j in y: 
          if i[0] == j[0]: 
           match.append(j) 
        return match 
    match = find_match(x, y) 
    
  • 採取一個新的水平,去年的變化,我通常與同類發電機

    更換模式

    def f(...): 
        return_value = [] 
        for... 
         return_value.append(foo) 
        return return_value 
    

    def f(...): 
        for... 
         yield foo 
    

    這將使上述功能

    def find_match(x, y): 
        for i in x: 
         for j in y: 
          if i[0] == j[0]: 
           yield j 
    

    另一種方式來表達這種發電機的作用是與發電機表達(j for i in x for j in y if i[0] == j[0])

1
if i[1] == j[1] 

檢查是否陣列的元件是相同的。你想要if i[0] == j[0]

否則,我覺得你的代碼很可讀,不一定會改變它。

2

我不知道我是否正確理解你的問題,但鑑於您的例子看來,你可能使用了錯誤的指標:

變化

if i[1] == j[1]: 

if i[0] == j[0]: 
+0

你是對的!感謝您指出了這一點。我編輯並納入並顯示輸出。 – 2010-03-29 14:43:19

0

一個simplier表達應該在這裏工作過:

list_of_lists = filter(lambda l: l[0][0] == l[1][0], zip(x, y)) 
map(lambda l: l[1], list_of_lists) 
+0

這比較了整個子列表,這似乎不是OP想要的。 – 2010-03-29 21:48:11

+0

另外,我不確定這是我所說的簡單。我幾乎總是發現使用list comprehensions比使用匿名函數的filter/map更好。例如,我認爲'[suby subx,suby in zip(x,y)if subx == suby]'是(我認爲)完全等價於你的代碼,但比'filter'更好一些, '地圖'版本。我認爲'如果subx [0] == suby [0]]'suby in suby in suby in suby in suby in suby [suby]更接近於OP的代碼。 – 2010-03-29 22:04:41

+0

@Mike我也喜歡列表解析功能,儘管功能接近程序偶爾會引誘我:-)。感謝指出錯誤,現在糾正。 – pajton 2010-03-29 22:22:10

1

您可以通過使用集合更簡單地做到這一點。

set_x = set([i[0] for i in x]) 
set_y = set([i[0] for i in y]) 
matches = list(set_x & set_y) 
+0

謝謝丹尼爾 - 我不知道我可以在集合中指定索引。我認爲該集只會返回列表中所有內容的完整匹配。 – 2010-03-29 14:44:49

+0

好主意[與集合一起工作]。然而,你應該強調,結果與原始程序的結果不同,關於排序和可能的重複值(根據結果的最終用途,這可能是也可能不重要)。 – mjv 2010-03-29 14:48:00

+0

@Seafoid:索引適用於x和y的子列表,而不適用於任何集合。 – mjv 2010-03-29 14:49:21