假设我有一组数据对,其中 index 0 是值,index 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']
}
]
我怎样才能有效地做到这一点?
9条答案
按热度按时间bfrts1fy1#
分两步来做。首先,创建一个字典。
然后,将字典转换为预期格式。
也可以使用itertools.groupby,但它要求输入首先进行排序。
注意,这两种方法都不遵守键的原始顺序。如果需要保持顺序,则需要OrderedDict。
cbwuti442#
Python内置的
itertools
模块实际上有一个groupby
函数,但是要分组的元素必须首先排序,使得要分组的元素在列表中是连续的:现在输入如下所示:
groupby
返回一个2元组的序列,格式为(key, values_iterator)
,我们需要将其转换为一个字典列表,其中'type'是键,'items'是values_iterator返回的元组的第0个元素的列表,如下所示:现在
result
包含了您想要的dict,正如您的问题中所述。不过,您可能会考虑只将其作为一个dict,按类型键控,并且每个值包含值列表。在当前表单中,要查找特定类型的值,必须遍历列表以查找包含匹配“type”键的dict,然后从中获取“items”元素。如果使用单个dict而不是1项dict列表,您可以通过主键查找主指令来查找特定类型的项目。使用
groupby
,如下所示:result
现在包含这个dict(这类似于@KennyTM的回答中的中间res
defaultdict):(If要将其简化为一行程序,可以:
或者使用新的听写理解形式:
fgw7neuy3#
这个答案类似于@PaulMcG的答案,但不需要对输入进行排序。
对于那些学习函数式编程的人来说,
groupBy
可以写在一行中(不包括导入!),而且与itertools.groupby
不同的是,它不需要对输入进行排序:(The在
lambda
中使用... or grp
的原因是,要使reduce()
工作,lambda
需要返回其第一个参数;因为list.append()
总是返回None
,所以or
也总是返回grp
,也就是说,这是一个绕过python限制的技巧,即lambda只能计算单个表达式。)这将返回一个dict,其键是通过计算给定函数找到的,其值是按原始顺序排列的原始项的列表。对于OP的示例,将其作为
groupBy(lambda pair: pair[1], input)
调用将返回以下dict:根据@PaulMcG的回答,OP请求的格式可以通过将其 Package 在列表解析中来找到。
hxzsmxv24#
我也喜欢panda simple grouping,它功能强大,简单,最适合大数据集
clj7thdc5#
下面的函数将通过具有任何索引的键快速(不需要排序)对任何长度的元组进行分组:
在您的问题中,要作为分组依据的键的索引是1,因此:
给予
这不完全是您要求的输出,但可能也适合您的需要。
3j86kqsm6#
luaexgnf7#
您可以使用convtools库,它可以为您的具体任务生成ad-hoc代码,并允许动态代码生成。
bz4sfanl8#
下面的代码段也是一种获得所需结果的方法-
jogvjijk9#
这不是很有效率,但它是Python式的。基本上,通过取组值的集合来计算不同的组,然后对于每个组,获取该组中的项。