2013-03-31 101 views
2

我是Python新手,遇到了一個我無法解決的問題。JSON,Python中的列表和遞歸

我已經從JSON解碼下面的分析樹到以下列表。

>>> tree 
['S', ['NP', ['DET', 'There']], ['S', ['VP', ['VERB', 'is'], ['VP', ['NP', ['DET', 'no'], ['NOUN', 'asbestos']], ['VP', ['PP', ['ADP', 'in'], ['NP', ['PRON', 'our'], ['NOUN', 'products']]], ['ADVP', ['ADV', 'now']]]]], ['.', '.']]] 

使用遞歸函數,我已能夠獲得包含終端單詞的列表。

def explorer(tree): 
    for sub in tree[1:]: 
        if(type(sub) == str): 
            allwords.append(sub) 
        else: 
            explorer(sub) 

>>> allwords 
['There', 'is', 'no', 'asbestos', 'in', 'our', 'products', 'no'.] 

現在我需要更換符合某些標準在原樹的話,讓我得到這樣的:

['S', ['NP', ['DET', 'There']], ['S', ['VP', ['VERB', 'is'], ['VP', ['NP', ['DET', 'no'], ['NOUN', '_REPLACED_']], ['VP', ['PP', ['ADP', 'in'], ['NP', ['PRON', 'our'], ['NOUN', 'products']]], ['ADVP', ['ADV', 'now']]]]], ['.', '.']]] 

我曾嘗試以下功能,但我不能向上傳播替代品,所以我總是得到相同的原始樹。

def replacer(tree): 
    string=[] 
    for sub in tree[1:]: 
        if(type(sub) == str): 
            if #'condition is true': 
                sub="_REPLACE_" 
                return sub 
            else: return sub    
        else: 
            string.extend(replacer(sub)) 
    print(string)     

我希望在如何實現結果的一些提示。先謝謝你。

+0

@Daniel Roseman感謝您的編輯! – Serge

回答

2

所以這裏有一個例子我如何使用列表解析來做這種事情。如果你不知道,列表的理解是something = [explorer(x) for x in something]。這也是遞歸發生的地方。你得到的是一個完全相同的結構列表,但你已經「去過」每個端點,並且可以檢查和替換事物。我做了一些隨意的替換。

>>> tree = ['S', ['NP', ['DET', 'There']], ['S', ['VP', ['VERB', 'is'], ['VP', ['NP', ['DET', 'no'], ['NOUN', 'asbestos']], ['VP', ['PP', ['ADP', 'in'], ['NP', ['PRON', 'our'], ['NOUN', 'products']]], ['ADVP', ['ADV', 'now']]]]], ['.', '.']]] 
>>> def explorer(something): 
     if type(something) == list: 
      something = [explorer(x) for x in something] 
     else: # You may want to check other conditions here, like if it's a string 
      if something == 'asbestos': 
       something = 'Oh my' 
      if something == 'S': 
       something = 'Z' 
     return something 

>>> explorer(tree) 
['Z', ['NP', ['DET', 'There']], ['Z', ['VP', ['VERB', 'is'], ['VP', ['NP', ['DET', 'no'], ['NOUN', 'Oh my']], ['VP', ['PP', ['ADP', 'in'], ['NP', ['PRON', 'our'], ['NOUN', 'products']]], ['ADVP', ['ADV', 'now']]]]], ['.', '.']]] 
>>> 

我剛剛在仔細閱讀你的文字後發現了一些東西。你是不是能夠「向上傳播替代」的原因是因爲你的循環的結構是這樣的:

for x in aList: 
    if x = somethingSpecial: 
     x = somethingElse 

這並不在Python工作,但是這並不:

for i,x in enumerate(aList): 
    if x = somethingSpecial: 
     aList[i] = somethingElse 

現在aList有本修改你想要的方式。如果你不知道enumerate()是什麼,只需複製/粘貼:

aList = ['a','b','c'] 
for i,x in enumerate(aList): 
    print(i,x) 
2

您的問題是,您在某些情況下重新調整字符串,並在其他人中打印列表。確保你的替代品總是返回一個字符串列表,你應該沒問題。

1

如果我正確理解你的問題,解決你的問題的一個方法是這樣的:

>>> tree = ['S', ['NP', ['DET', 'There']], ['S', ['VP', ['VERB', 'is'], ['VP', ['NP', ['DET', 'no'], ['NOUN', 'asbestos']], ['VP', ['PP', ['ADP', 'in'], ['NP', ['PRON', 'our'], ['NOUN', 'products']]], ['ADVP', ['ADV', 'now']]]]], ['.', '.']]] 
>>> def replacer(tree): 
     for i, sub in enumerate(tree[1:]): 
      if type(sub) == str and sub == 'asbestos': 
       tree[i+1] = '__REPLACE__' 
      else: 
       replacer(sub) 

如果您進行了更改樹[1:],你實際上並沒有進行更改到列表而是對拼接。所以enumerate函數可以解決這個問題。您的sub="_REPLACE_"實際上並未更改列表。它僅爲名稱sub分配一個新值。

結果:

>>> replacer(tree) 
>>> tree 
['S', ['NP', ['DET', 'There']], ['S', ['VP', ['VERB', 'is'], ['VP', ['NP', ['DET', 'no'], ['NOUN', '__REPLACE__']], ['VP', ['PP', ['ADP', 'in'], ['NP', ['PRON', 'our'], ['NOUN', 'products']]], ['ADVP', ['ADV', 'now']]]]], ['.', '.']]] 

要獲得一個新的列表像你的第一個函數創建,你可以簡單地套用你的第一個功能,新tree列表:

>>> explorer(tree) 
['There', 'is', 'no', '__REPLACE__', 'in', 'our', 'products', 'now', '.']