2012-07-09 68 views
0

所以我的主要目標很簡單,我希望在使用單個鍵時返回多個值。但是,我收到錯誤和令人困惑的行爲。我是Python新手,所以我完全期待這個問題存在一個簡單的原因。python中的一個鍵的多個值

我有一個對象列表list其中只包含對象的索引。即

1 
2 
3 
4 
etc.. 

和包含每個對象所屬的組的文件以相同的順序列出。該文件是n行的單個值(n爲對象的列表的長度爲好。)即文件看起來像這樣:

2 
5 
2 
4 
etc.. 

意味着第一對象屬於第2組,所述第二對象中第5組,第2組第4組和第4組。這個文件將根據我的輸入文件而改變。我嘗試了以下兩個建議(我可以找到)。

編輯:我的最終目標是:將字典的組號作爲鍵和組中的對象作爲值。

我看着這個StackOverflow的question第一求助,因爲它是如此的相似,並結束了這段代碼:

def createdDict(list, file): 

    f = open(file, 'r') 
    d={} 
    i=0 

    for line in f: 
     groupIndex = int(line) 
     if groupIndex in d: 
      d[groupIndex].append(list[i]) 
     else: 
      d[groupIndex] = list[i] 
     i +=1 
    print d 
    f.close() 

而這個錯誤:

AttributeError: 'Element' object has no attribute 'append' 

d[groupIndex]僅僅是一個字典,它的鍵和groupIndex也應該只是一個整數..不是我在前面創建的類中的一個對象。 (爲什麼會出現這個錯誤?)

然後我在修改我的代碼後,遇到這個other question就像下面這樣,因爲我認爲這是完成我的任務的另一種方式。我的代碼則是這樣的:

def createdDict(list, file): 

    f = open(file, 'r') 
    d={} 
    i=0 

    for line in f: 
     groupIndex = int(line) 
     if groupIndex in d: 
      d.setdefault('groupIndex', []).append(list[i]) 
     else: 
      d[groupIndex] = list[i] 
     i +=1 
    print d 
    f.close() 

這段代碼中的錯誤或我要,而是(我相信)是在小組的最後一個對象是什麼並沒有結束......所以print d給我放置在組中的鍵和最後一個對象(而不是所需的:該組中的所有對象),然後終端隨機分出groupIndex,然後是list中的所有對象。

我的問題:我在這裏錯過了什麼?人們對我所鏈接的問題的答案讚不絕口,所以它們很可能是正確的,我可能會錯誤地實施它們。我不需要對這兩個過程進行更正,但是對於將多個值附加到一個密鑰的問題的最有效答案。什麼是完成這項任務最pythonic的方式?

編輯2:如果這有幫助,這裏是第一種方法引用錯誤的類。我不知道它是如何定義這個代碼的任何部分作爲這個類的一部分。我還沒有真正開發過,但我所有的答案,因此,如果這有助於定位錯誤:

class Element(object): 
    def __init__(self, globalIndex): 
     self.globalIndex = globalIndex 
    def GetGlobalIndex (self): 
     return self.globalIndex 

globalIndex是對象(元素)的一個單獨的索引。與我目前的問題,我正在列出這些元素(這是前面提到的列表),並根據我的文件(前面也提到)將它們分組爲較小的組。爲什麼我認爲它應該不重要,這個列表本質上是對整數的計數......它會如何混淆我的代碼?

+1

什麼是您預期的輸出?字典不支持'append()'這就是爲什麼你會得到'AttributeError'。 – 2012-07-09 19:35:33

+0

我想要一個字典,其中的組號碼是關鍵字,其中的對象是值。 – Ason 2012-07-09 19:36:43

+0

@AshwiniChaudhary:錯誤提到一個'Element'對象。我猜在OP的代碼中有一個類沒有在這裏顯示 – inspectorG4dget 2012-07-09 19:37:36

回答

6

你的問題的基礎是在這一行:

d[groupIndex] = list[i] 

換句話說,當一個鍵不在字典中,該鍵下添加一個單個值Element對象)。下次你看到那個鍵時,你試圖追加到那個單一的值。但是你不能附加到單個值。你需要一個容器類型,例如一個列表來追加。 Python不會奇蹟般地把你的Element對象變成一個列表!

解決方案很簡單。如果你想你的字典的值是列表,然後這樣做。當您添加的第一個項目,追加一個元素的列表:

d[groupIndex] = [list[i]] 

或者,你可以把原來的列表的一個項目片。這將成爲一個列表。

d[groupIndex] = list[i:i+1] 

現在字典的值總是列表,並且您可以將第二個和後續值附加到它們,而不會出錯。

由於ecatmur指出,您可以使用d.setdefault(groupIndex, []).append(list[i])進一步簡化此(取消if聲明)。如果該鍵不存在,那麼該值將被視爲一個空列表,並且您總是追加新的項目。您也可以使用collections.defaultdict(list)

+0

絕對完美。謝謝你抓住這個! – Ason 2012-07-09 20:50:25

2

只需使用

d.setdefault(groupIndex, []).append(list[i]) 

這將檢查groupIndex是否d,所以你不需要if groupIndex in d:線。

2
from itertools import izip 
from collections import defaultdict 

dd = defaultdict(list) 
with open('filename.txt') as fin: 
    for idx, line in izip(my_list, fin): 
     num = int(line) 
     defaultdict[num].append(idx) 

這將創建列表的默認類型defaultdict,所以你可以不追加使用setdefault。然後從文件中讀取my_list的每個元素與相應的行相結合,將行轉換爲整數,然後將相應的索引添加到組(由num表示)。

1

在第一次嘗試中,您似乎正確理解將第一個元素添加到字典項目是一種特殊情況,並且由於字典項目沒有值,因此您無法追加。

在你的情況下,你將它設置爲列表[i]。但是,list [i]不是一個列表,因此在後面的迭代中不能運行追加。

我會做這樣的事情:

for line in f: 
    groupIndex = int(line) 
    try: 
     blah = d[groupIndex] # to check if it exists 
    except: 
     d[groupIndex] = [] # if not, assign empty list 

    d[groupIndex].append(list[i]) 
print d 
f.close() 
+1

我從其他帖子看到,defaultdict和setdefault是在解決方案中構建的。這就是爲什麼你甚至通過回答:-) – 2012-07-09 19:43:34

+0

也是一個很好的答案! – Ason 2012-07-09 20:51:01