所以我的主要目标很简单,我希望在使用单个键时返回多个值。但是我遇到了错误和令人困惑的行为。我是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)。根据我当前的问题,我正在列出这些元素(这是前面提到的列表),并根据我的文件将它们分组到较小的组中(前面也提到过)。为什么我认为这不重要,列表基本上是整数的计数......我的代码会怎么样?
答案 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()