12

您好想要一个有序的字典,其中的键具有值列表。

从下面的代码中,我可以获得带有键列表的字典,但缺少插入顺序。

from collections import defaultdict

keys=['blk','pri','ani']
vals1=['blocking','primary','anim']
vals2=['S1','S2','S3']
dic = defaultdict(list)

i=0

for key in keys:
    dic[key].append(vals1[i])
    dic[key].append(vals2[i])

    i += 1

print dic

我得到以下结果

defaultdict(<type 'list'>, {'pri': ['primary', 'S2'], 'ani': ['anim', 'S3'], 'blk': ['blocking', 'S1']})

在这里我丢失了插入订单。

我知道 Python 中的 defaultdict 对象按定义是无序的

而且我知道如果您需要插入值的顺序,我们需要使用OrderedDict (它在 Python 2.7 和 3.x 中可用)

所以改变了我的代码如下

从下面的代码我可以得到我需要的东西。

from collections import defaultdict,OrderedDict

keys=['blk','pri','ani']
vals1=['blocking','primary','anim']
vals2=['S1','S2','S3']
dic = OrderedDict(defaultdict(list))

i=0

for key in keys:
    dic[key].append(vals1[i])
    dic[key].append(vals2[i])

    i += 1

print dic

现在我收到以下错误

Traceback (most recent call last):
  File "Dict.py", line 18, in <module>
    dic[key].append(vals1[i])
KeyError: 'blk' 

谁能告诉我如何得到我正在尝试的东西。

4

3 回答 3

10

如果您真的想要“有序”“默认”行为,我想我会创建一个自定义字典类来为我处理一切:

from collections import OrderedDict

class DefaultListOrderedDict(OrderedDict):
    def __missing__(self,k):
        self[k] = []
        return self[k]

keys=['blk','pri','ani']
vals1=['blocking','primary','anim']
vals2=['S1','S2','S3']
dic = DefaultListOrderedDict()
for i,key in enumerate(keys):
    dic[key].append(vals1[i])
    dic[key].append(vals2[i])

print dic

defaultdict将比其他解决方案表现得更像,但它会保留它的顺序,而且它真的不是很多代码:)。最后,您甚至可以覆盖__init__以允许用户传递他们想要的任何“工厂”(而不是硬编码list)。我将把它作为练习留给感兴趣的读者。Python 太酷了。

于 2012-11-07T07:41:02.167 回答
3

OrderedDict环绕的问题defaultdict(list)在于它是这样评估的:

  1. 创建 的空实例defaultdict
  2. 创建一个 的实例OrderedDict,然后用 (当前为空)的内容对其进行初始化defaultdict,然后丢弃旧的defaultdict,因为不再引用它。

这不会像您想要的那样结合他们的行为。

我见过的标准成语是dict.setdefault方法。

from collections import OrderedDict

keys=['blk','pri','ani']
vals1=['blocking','primary','anim']
vals2=['S1','S2','S3']
dic = OrderedDict()

i=0

for key in keys:
    dic.setdefault(key, []).append(vals1[i])
    dic.setdefault(key, []).append(vals2[i])

    i += 1

print dic

像 defaultdict 一样,这会在您第一次访问它时创建一个值,尽管我认为它的效率有点低。

我会使用这种方法:

from collections import OrderedDict
dic = OrderedDict(zip(keys, zip(vals1, vals2)))
print dic
于 2012-11-07T07:27:56.733 回答
2

试试这个:

from collections import OrderedDict

keys=['blk','pri','ani']
vals1=['blocking','primary','anim']
vals2=['S1','S2','S3']
print OrderedDict(zip(keys, zip(vals1, vals2)))
于 2012-11-07T07:24:24.833 回答