2013-03-22 68 views
5

我觉得Python应该有一个内置的这样做。获取项目列表并将它们转换为字典映射关键字到具有该关键字的项目列表。按键分组项目?

这是很容易做到:

# using defaultdict 
lookup = collections.defaultdict(list) 
for item in items: 
    lookup[key(item)].append(item) 

# or, using plain dict 
lookup = {} 
for item in items: 
    lookup.setdefault(key(item), []).append(item) 

但这是不够频繁的使用情况,一个内置的功能将是很好的。我可以实现它自己,因为这样的:

def grouped(iterable, key): 
    result = {} 
    for item in iterable: 
     result.setdefault(key(item), []).append(item) 
    return result 

lookup = grouped(items, key) 

这比在几个重要的方面itertools.groupby不同。为了从groupby相同的结果,你必须要做到这一点,这是一个有点难看:

lookup = dict((k, list(v)) for k, v in groupby(sorted(items, key=key), key)) 

一些例子:

>>> items = range(10) 
>>> grouped(items, lambda x: x % 2) 
{0: [0, 2, 4, 6, 8], 1: [1, 3, 5, 7, 9]} 

>>> items = 'hello stack overflow how are you'.split() 
>>> grouped(items, len) 
{8: ['overflow'], 3: ['how', 'are', 'you'], 5: ['hello', 'stack']} 

有没有更好的办法?

+1

我不明白这是一个“足够频繁的用例”。我很少使用它,当我必须使用'defaultdict'时,它非常完美。 AFAIK没有任何内置功能可以完成您想要的功能。 – Bakuriu 2013-03-22 21:39:21

+0

你可能是对的,但我的一部分人认为这和groupby一样有效。 – FogleBird 2013-03-23 00:16:11

回答

3

我也发布了这个问题comp.lang.python,并且共识似乎是这实际上不足以保证一个内置函数。所以,使用明显的方法是最好的。他们工作,他们是可读的。

# using defaultdict 
lookup = collections.defaultdict(list) 
for item in items: 
    lookup[key(item)].append(item) 

# or, using plain dict 
lookup = {} 
for item in items: 
    lookup.setdefault(key(item), []).append(item) 

我要删除我的问题,但我还不如离开这个位置的情况下,任何人通过它绊倒寻找信息。

+1

请参阅下面的答案,了解如何提取函数以执行上述操作,但使用与“groupby”大致相同的API。 – tobych 2013-04-30 21:37:28

1

如果你想要的东西,用大致相同的API为groupby,你可以使用:

def groupby2(iterable, keyfunc): 
    lookup = collections.defaultdict(list) 
    for item in iterable: 
     lookup[keyfunc(item)].append(item) 
    return lookup.iteritems() 

所以这是一样的你上面的例子,但制作成返回查找表你”的iteritems功能已经建成。