为了账号安全,请及时绑定邮箱和手机立即绑定

Python分组依据

Python分组依据

aluckdog 2019-10-15 14:04:10
假设我有一组数据对,其中索引0是值,索引1是类型:input = [          ('11013331', 'KAT'),           ('9085267',  'NOT'),           ('5238761',  'ETH'),           ('5349618',  'ETH'),           ('11788544', 'NOT'),           ('962142',   'ETH'),           ('7795297',  'ETH'),           ('7341464',  'ETH'),           ('9843236',  'KAT'),           ('5594916',  'ETH'),           ('1550003',  'ETH')        ]我想按它们的类型(按第一个索引字符串)将它们分组,如下所示:result = [            {              type:'KAT',              items: ['11013331', '9843236']            },           {             type:'NOT',              items: ['9085267', '11788544']            },           {             type:'ETH',              items: ['5238761', '962142', '7795297', '7341464', '5594916', '1550003']            }         ] 如何有效地做到这一点?
查看完整描述

3 回答

?
LEATH

TA贡献1936条经验 获得超6个赞

分两步完成。首先,创建字典。


>>> input = [('11013331', 'KAT'), ('9085267', 'NOT'), ('5238761', 'ETH'), ('5349618', 'ETH'), ('11788544', 'NOT'), ('962142', 'ETH'), ('7795297', 'ETH'), ('7341464', 'ETH'), ('9843236', 'KAT'), ('5594916', 'ETH'), ('1550003', 'ETH')]

>>> from collections import defaultdict

>>> res = defaultdict(list)

>>> for v, k in input: res[k].append(v)

...

然后,将该字典转换为预期的格式。


>>> [{'type':k, 'items':v} for k,v in res.items()]

[{'items': ['9085267', '11788544'], 'type': 'NOT'}, {'items': ['5238761', '5349618', '962142', '7795297', '7341464', '5594916', '1550003'], 'type': 'ETH'}, {'items': ['11013331', '9843236'], 'type': 'KAT'}]

使用itertools.groupby也可以,但是它要求输入首先被排序。


>>> sorted_input = sorted(input, key=itemgetter(1))

>>> groups = groupby(sorted_input, key=itemgetter(1))

>>> [{'type':k, 'items':[x[0] for x in v]} for k, v in groups]

[{'items': ['5238761', '5349618', '962142', '7795297', '7341464', '5594916', '1550003'], 'type': 'ETH'}, {'items': ['11013331', '9843236'], 'type': 'KAT'}, {'items': ['9085267', '11788544'], 'type': 'NOT'}]

请注意,这两个都不遵守键的原始顺序。如果需要保留订单,则需要一个OrderedDict。


>>> from collections import OrderedDict

>>> res = OrderedDict()

>>> for v, k in input:

...   if k in res: res[k].append(v)

...   else: res[k] = [v]

... 

>>> [{'type':k, 'items':v} for k,v in res.items()]

[{'items': ['11013331', '9843236'], 'type': 'KAT'}, {'items': ['9085267', '11788544'], 'type': 'NOT'}, {'items': ['5238761', '5349618', '962142', '7795297', '7341464', '5594916', '1550003'], 'type': 'ETH'}]


查看完整回答
反对 回复 2019-10-15
?
呼唤远方

TA贡献1856条经验 获得超11个赞

Python的内置itertools模块实际上具有一个groupbyfunction,但是为此,必须首先对要分组的元素进行排序,以使要分组的元素在列表中是连续的:


from operator import itemgetter

sortkeyfn = itemgetter(1)

input = [('11013331', 'KAT'), ('9085267', 'NOT'), ('5238761', 'ETH'), 

 ('5349618', 'ETH'), ('11788544', 'NOT'), ('962142', 'ETH'), ('7795297', 'ETH'), 

 ('7341464', 'ETH'), ('9843236', 'KAT'), ('5594916', 'ETH'), ('1550003', 'ETH')] 

input.sort(key=sortkeyfn)

现在输入看起来像:


[('5238761', 'ETH'), ('5349618', 'ETH'), ('962142', 'ETH'), ('7795297', 'ETH'),

 ('7341464', 'ETH'), ('5594916', 'ETH'), ('1550003', 'ETH'), ('11013331', 'KAT'),

 ('9843236', 'KAT'), ('9085267', 'NOT'), ('11788544', 'NOT')]

groupby返回格式为的2元组序列(key, values_iterator)。我们想要的是将其转换为字典列表,其中“类型”是键,“项目”是values_iterator返回的元组的第0个元素的列表。像这样:


from itertools import groupby

result = []

for key,valuesiter in groupby(input, key=sortkeyfn):

    result.append(dict(type=key, items=list(v[0] for v in valuesiter)))

现在result包含您想要的字典,如您的问题所述。


但是,您可能会考虑仅对此做出一个单独的dict,以类型为键,并且每个值都包含值列表。在当前形式中,要查找特定类型的值,必须遍历列表以查找包含匹配的“ type”键的字典,然后从中获取“ items”元素。如果您使用单个词典而不是一个1-item词典的列表,则可以通过在主词典中进行单键查找来查找特定类型的项目。使用groupby,这看起来像:


result = {}

for key,valuesiter in groupby(input, key=sortkeyfn):

    result[key] = list(v[0] for v in valuesiter)

result现在包含此字典(这类似于res@KennyTM答案中的中间defaultdict):


{'NOT': ['9085267', '11788544'], 

 'ETH': ['5238761', '5349618', '962142', '7795297', '7341464', '5594916', '1550003'], 

 'KAT': ['11013331', '9843236']}

(如果您希望将其减少为单层,则可以:


result = dict((key,list(v[0] for v in valuesiter)

              for key,valuesiter in groupby(input, key=sortkeyfn))

或使用新奇的dict-comprehension形式:


result = {key:list(v[0] for v in valuesiter)

              for key,valuesiter in groupby(input, key=sortkeyfn)}


查看完整回答
反对 回复 2019-10-15
  • 3 回答
  • 0 关注
  • 514 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信