python中一个键的多个值

时间:2012-07-09 19:32:39

标签: python dictionary

所以我的主要目标很简单,我希望在使用单个键时返回多个值。但是我遇到了错误和令人困惑的行为。我是Python的新手,所以我完全期望这个问题有一个简单的原因。

我有一个对象列表list,它只包含对象的索引。即

1
2
3
4 
etc.. 

和包含每个对象所属的组的文件,以相同的顺序列出。该文件是n行的单个值(n也是对象列表的长度。)即文件如下所示:

2
5
2
4
etc..

表示第一个对象属于组2,第二个对象属于组5,第三个属于组2,第四个属于组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是一个单独的对象索引(Elements)。根据我当前的问题,我正在列出这些元素(这是前面提到的列表),并根据我的文件将它们分组到较小的组中(前面也提到过)。为什么我认为这不重要,列表基本上是整数的计数......我的代码会怎么样?

4 个答案:

答案 0 :(得分:6)

问题的基础在这一行:

d[groupIndex] = list[i]

换句话说,当一个键不在字典中时,您在该键下添加一个单值Element对象)。下次看到该键时,您会尝试附加到该单个值。但是你不能附加单个值。您需要附加容器类型(例如列表)。 Python并没有神奇地将你的Element对象变成一个列表!

解决方案很简单。如果您希望字典的值为列表,则执行此操作。添加第一个项目时,请附加一个元素列表:

d[groupIndex] = [list[i]]

或者,您可以获取原始列表的单项切片。这已经是一个清单了。

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

现在字典的值始终是列表,您可以将第二个及后续值附加到它们而不会出错。

正如 ecatmur 所指出的,您可以使用if进一步简化此操作(取消d.setdefault(groupIndex, []).append(list[i])语句)。如果该键不存在,则该值将被视为空列表,并且您只需附加新项。您也可以使用collections.defaultdict(list)

答案 1 :(得分:2)

只需使用

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

这将检查groupIndex是否在d中,因此您不需要if groupIndex in d:行。

答案 2 :(得分: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表示)。

答案 3 :(得分: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()