2012-08-01 55 views
2

Possible Duplicate:
Remove items from a list while iterating in Python的Python:元組的搜索列表,刪除整個索引

我有一個相當嵌入列表,具體地說,它是元組的列表的列表。爲了簡化事情,整個列表是一個句子列表。在每個句子中,每個單詞都被製成一個元組,其中包含有關該單詞的信息。每個句子中的最後一個元組包含關於說話者的信息,但如果需要的話可以刪除。

我想通過這些元組進行搜索,如果找到某個值,則刪除整個句子。

這裏是一個示例清單:

sentenceList = [[('the', 'det', '1|2|DET'), ('duck', 'n', '2|3|SUBJ'), ('xxx', 'unk', '3|0|ROOT'), ('*MOT', 373)], 
       [('yyy', 'unk', '1|0|ROOT'), ('*CHI', 375)], 
       [('what', 'pro', '1|2|OBJ'), ('happen-PAST', 'v', '2|0|ROOT'), ('to', 'prep', '3|2|JCT'), ('the', 'det', '4|5|DET'), ('duck', 'n', '5|3|POBJ'), ('*MOT', 378)], 
       [('boom', 'int', '1|0|ROOT'), ('*CHI', 379)]] 

如果一個句子中包含兩種'xxx''yyy',我想刪除整個句子。我試過的代碼是:

wordList = ['xxx','yyy'] 
for sentence in sentenceList: 
    for wordTuple in sentence: 
     for entry in wordTuple: 
      if entry in wordList: 
       del sentence 

這應該刪除整個句子,即:

[('the', 'det', '1|2|DET'), ('duck', 'n', '2|3|SUBJ'), ('xxx', 'unk', '3|0|ROOT'), ('*MOT', 373)], [('yyy', 'unk', '1|0|ROOT'), ('*CHI', 375)] 

然而,這段代碼似乎並沒有被完成的任務。任何想法如何解決它?謝謝!

+1

我猜測問題是你正在從列表中刪除列表中的一個成員('sentenceList'),而你正在遍歷列表。 [這個答案](http://stackoverflow.com/questions/1207406/remove-items-from-a-list-while-iterating-in-python)應該可以幫助你解決這個問題。 – 2012-08-01 19:35:52

+0

謝謝@SamMussmann!我遇到過,但不知道如何適應我的具體情況。 – 2012-08-01 19:42:58

+0

我已經爲您的問題添加了該答案的改編答案。我希望這有幫助。 :-) – 2012-08-01 21:56:06

回答

1

當您用for迭代它時嘗試修改列表是很危險的。你真正想要的是一個while循環:

contrived_data = [[(1, 1, 1), ('hello', 'bar')], [(222, 3, 4), ('norweigan', 'blue')], [('anthrax', 'ripple'), (42, 'life')]] 

looking_for = (1, 'life') 

index = 0 
while index < len(contrived_data): 
    for two_pull in contrived_data[index]: 
     for item in looking_for: 
      if item in two_pull: 
       print(contrived_data.pop(index)) 
       index -= 1 
       break # Only jumps out of the innermost loop 
    index += 1 

,並應比複製您的原始列表更大的數據集更有效。

+0

但是,這將如何工作的單詞列表(或集),但?由於這隻檢查「1」,我怎麼能改變它來檢查一堆值? – 2012-08-01 20:04:07

+0

這也似乎拋出「IndexError:彈出索引超出範圍。」難道我做錯了什麼? – 2012-08-01 20:22:34

+0

我在那裏添加了另一個循環,以及適當的'break'。更新是否仍然會拋出異常?確保您的縮進級別在所有方面都是正確的。而且,如果它仍然中斷,請發佈您的更新代碼,我會看看我能做些什麼。 – 2012-08-01 21:24:38

2
wordList = set(('xxx','yyy')) 
for sentence in sentenceList[:]: 
    removed = False 
    for wordTuple in sentence: 
     for entry in wordTuple: 
      if entry in wordList: 
       sentenceList.remove(sentence) 
       removed = True 
       break 
      # end of if 
     # end for each entry 
     if removed: 
      break 
    # end for each word tuple 
# end for each sentence 

注:

  • 遍歷列表的(淺)的副本,以避免從修改你穿越
  • 從列表中刪除的對象集合出現的錯誤,而不是簡單地從本地命名空間
  • 刪除變量名,這是效率不高的大型數據集
+0

一個集合對於'wordList'來說是一個更好的數據結構。 – mgilson 2012-08-01 19:39:39

+0

謝謝!這當然有訣竅。有幾個問題:(1)向SentenceList添加「[:]」是做什麼的? (2)關於如何使代碼更高效的任何快速建議?我將把它應用於大型數據集。 (3)對於@mgilson,我該如何將它聲明爲一個集合? – 2012-08-01 19:42:12

+0

添加'[:]'列表的淺表副本。你可以創建一個像'wordList = set(['xxx','yyy'])''的集合。 – 2012-08-01 19:44:45

1

This answer與此類似。爲了應用它,我們需要一個謂詞(一個參數的函數,它只返回TrueFalse)確定條目是否應該保留。

既然我們有一個叫做wordList在一組目標詞:

wordList = set(('xxx', 'yyy')) 

這個謂詞應該工作:

def keep_sentence(sentence): 
    for wordTuple in sentence: 
     for entry in wordTuple: 
      if entry in wordList: 
       return False 
    return True # Only executed if we didn't return false earlier 

現在,我們有一個謂語,我們可以更換的sentenceList內容只有keep_sentence告訴我們應該保留的句子:

sentenceList[:] = [x for x in sentenceList if keep_sentence(x)] 

至於應用到大型數據集 - 可能不會有比這更快的算法(或其他答案之一),沒有並行化你的代碼。爲什麼?爲了檢查每個句子是否包含目標詞之一,我們必須查看每個句子中的每個詞。你可以用一些不變的因素來減少你在每個句子上花費的時間,但這不會有很大的幫助。

如果您對此感興趣,您可能需要查看multiprocessing模塊,尤其是process pools