18

如果 adefaultdict可以按照以下几行进行初始化,那将很方便

d = defaultdict(list, (('a', 1), ('b', 2), ('c', 3), ('d', 4), ('a', 2),
   ('b', 3)))

生产

defaultdict(<type 'list'>, {'a': [1, 2], 'c': [3], 'b': [2, 3], 'd': [4]})

相反,我得到

defaultdict(<type 'list'>, {'a': 2, 'c': 3, 'b': 3, 'd': 4})

为了得到我需要的东西,我最终不得不这样做:

d = defaultdict(list)
for x, y in (('a', 1), ('b', 2), ('c', 3), ('d', 4), ('a', 2), ('b', 3)):
    d[x].append(y)

这比 IMO 多一步是必要的,我在这里遗漏了什么吗?

4

5 回答 5

20

您显然缺少的defaultdictdict. 第一个参数所做的只是为丢失的键提供工厂函数。当您初始化 adefaultdict时,您正在初始化 a dict

如果你想生产

defaultdict(<type 'list'>, {'a': [1, 2], 'c': [3], 'b': [2, 3], 'd': [4]})

您应该以初始化任何其他dict值为列表的方式对其进行初始化:

d = defaultdict(list, (('a', [1, 2]), ('b', [2, 3]), ('c', [3]), ('d', [4])))

如果您的初始数据必须采用第二个元素始终为整数的元组形式,则只需使用for循环即可。你称之为额外的一步;我称之为清晰而明显的方法。

于 2013-08-29T21:28:48.753 回答
10

defaultdict您描述的行为与其他行为不一致。好像你想要的是FooDict这样的

>>> f = FooDict()
>>> f['a'] = 1
>>> f['a'] = 2
>>> f['a']
[1, 2]

我们可以这样做,但不能使用 defaultdict;让我们称之为 AppendDict

import collections

class AppendDict(collections.MutableMapping):
    def __init__(self, container=list, append=None, pairs=()):
        self.container = collections.defaultdict(container)
        self.append = append or list.append
        for key, value in pairs:
            self[key] = value

    def __setitem__(self, key, value):
        self.append(self.container[key], value)

    def __getitem__(self, key): return self.container[key]
    def __delitem__(self, key): del self.container[key]
    def __iter__(self): return iter(self.container)
    def __len__(self): return len(self.container)
于 2013-08-29T21:31:08.287 回答
4

排序并itertools.groupby走很长的路:

>>> L = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('a', 2), ('b', 3)]
>>> L.sort(key=lambda t:t[0])
>>> d = defaultdict(list, [(tup[0], [t[1] for t in tup[1]]) for tup in itertools.groupby(L, key=lambda t: t[0])])
>>> d
defaultdict(<type 'list'>, {'a': [1, 2], 'c': [3], 'b': [2, 3], 'd': [4]})

为了使它更像一个单行:

L = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('a', 2), ('b', 3)]
d = defaultdict(list, [(tup[0], [t[1] for t in tup[1]]) for tup in itertools.groupby(sorted(L, key=operator.itemgetter(0)), key=lambda t: t[0])])

希望这可以帮助

于 2013-08-29T21:06:38.200 回答
3

我认为其中大部分都是为了避免一个简单的 for循环,这是很多烟雾和镜子:

di={}
for k,v in [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('a', 2),('b', 3)]:
    di.setdefault(k,[]).append(v)
# di={'a': [1, 2], 'c': [3], 'b': [2, 3], 'd': [4]}

如果您的目标是一行,并且您想要我根本无法认可或支持的滥用语法,您可以使用副作用理解:

>>> li=[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('a', 2),('b', 3)]
>>> di={};{di.setdefault(k[0],[]).append(k[1]) for k in li}
set([None])
>>> di
{'a': [1, 2], 'c': [3], 'b': [2, 3], 'd': [4]}

如果您真的想过度阅读不可读的内容:

>>> {k1:[e for _,e in v1] for k1,v1 in {k:filter(lambda x: x[0]==k,li) for k,v in li}.items()}
{'a': [1, 2], 'c': [3], 'b': [2, 3], 'd': [4]}

你不想那样做。使用 for 循环卢克!

于 2013-08-29T21:37:22.823 回答
1
>>> kvs = [(1,2), (2,3), (1,3)]
>>> reduce(
...   lambda d,(k,v): d[k].append(v) or d,
...   kvs,
...   defaultdict(list))
defaultdict(<type 'list'>, {1: [2, 3], 2: [3]})
于 2014-12-26T21:02:35.120 回答