Python 通过相等的第一个字段合并/分组/部分合并列表列表,以字符串形式连接第二个字段,并在其他字段中写入相同的数据
例如,我有一个列表,我可以按前两个字段对其进行排序,这样就可以了:Python 通过相等的第一个字段合并/分组/部分合并列表列表,以字符串形式连接第二个字段,并在其他字段中写入相同的数据,python,algorithm,list,grouping,Python,Algorithm,List,Grouping,例如,我有一个列表,我可以按前两个字段对其进行排序,这样就可以了: import operator list = [ ['1', '2', '3'], ['1', '5', '6'], ['2', '8', '9', '8', '17'], ['2', '3', '5', '3'], ['1', '14', '89', '34', '15'], ] sorted_list = sorted(list, key=operator.itemgetter(0,
import operator
list = [
['1', '2', '3'],
['1', '5', '6'],
['2', '8', '9', '8', '17'],
['2', '3', '5', '3'],
['1', '14', '89', '34', '15'],
]
sorted_list = sorted(list, key=operator.itemgetter(0, 1))
获取:
['1', '14', '89', '34', '15']
['1', '2', '3']
['1', '5', '6']
['2', '3', '5', '3']
['2', '8', '9', '8', '17']
所以,我需要的是——按第一个字段组合这些列表,第一步是[0][0]、[0][1]、[0][2]中的“1”,然后我用逗号将第二个字段连接起来:“14:2:5”,我不在乎,我将这3个列表的哪一部分附加,所以,在“|”之后可以是:
['1', '14:2:5',| '89', '34', '15']
['1', '14:2:5',| '3']
['1', '14:2:5',| '6']
(在大多数情况下,“|”之后的数据将与第一个字段匹配)
最后,我想要的是:
['1', '14:2:5', '89', '34', '15']
['2', '3:8', '5', '3']
我目前正处于某种for循环中,并一直在获取indexer:-(
我觉得这应该是一种更简单的pythonic方法。
还不知道如何找到这个算法以及它是如何调用的。类似列表列表的东西减少了映射收缩规范化元素,通过元素值附加另一个
非常感谢您的帮助,python中的事情仍然让我感到惊讶,从所有答案来看,python 3最终可以做到多么酷:
# -*- coding: utf-8 -*-
import operator
import itertools
from natsort import humansorted
list_to_sort = [
['1', 'A', '3'],
['1', '5', '6'],
['1', '1', '10', '11', '12'],
['t', 'S', '7', '0asdf'],
['2', '8', '9', '8', '17'],
['2', '705', '5', '3'],
['2', 'checks', 'df', '1'],
['1', '14', '89', '34', '15'],
]
sorted_list = humansorted(list_to_sort, key=operator.itemgetter(0, 1))
grouped = [list(g) for k, g in itertools.groupby(sorted_list, key=lambda x: x[0])]
out = [[gg[0][0], ':'.join([g[1] for g in gg])] + gg[0][2:] for gg in grouped]
for elem in out:
print(elem)
一旦您对列表进行了排序,以便第一个字段组是连续的,您就可以使用来完成繁重的工作:
>>> grouped = [list(g) for k,g in groupby(sorted_list, key=lambda x: x[0])]
>>> grouped
[[['1', '14', '89', '34', '15'], ['1', '2', '3'], ['1', '5', '6']], [['2', '3', '5', '3'], ['2', '8', '9', '8', '17']]]
>>> out = [[gg[0][0], ':'.join([g[1] for g in gg])] + gg[0][2:] for gg in grouped]
>>> out
[['1', '14:2:5', '89', '34', '15'], ['2', '3:8', '5', '3']]
您可以使用字典来保留带有公共第一项的子列表,然后使用带有
zip
和join
的列表理解来创建所需的结果:
>>> d={}
>>>
>>> for i,*j in sorted_list:
... d.setdefault(i,[]).append(iter(j))
...
>>> [[i,':'.join(next(zip(*j)))]+next(j)[1:] for i,j in d.items()]
[['1', '14:2:5', '89', '34', '15'], ['2', '3:8', '5', '3']]
但请注意,此代码是用python 3编写的。如果您使用的是python 2,则可以使用itertools.izip
而不是zip
,要创建字典,可以执行以下操作:
>>> for i in sorted_list:
... d.setdefault(i[0],[]).append(iter(i[1:]))
您可以使用如下所示的一对函数来完成此操作。第一个函数名为
grouper
,是一个生成器函数,当需要从流程生成中间结果时,它通常非常有用,因为在返回多个中间结果之前,需要进行大量的初始化和/或内务处理
正如@Ashwini Chaudhary在一篇评论中指出的那样,您在代码中是按照字典顺序而不是数字顺序对字段进行排序的,所以这个问题也得到了纠正
import operator
def grouper(a_list):
if a_list:
sorted_list = sorted(a_list,
key=lambda e, get_items=operator.itemgetter(0, 1):
map(int, get_items(e)))
g = [sorted_list[0]]
for x in sorted_list[1:]:
if x[0] == g[-1][0]:
g.append(x)
else:
yield g
g = [x]
yield g
def combiner(a_list):
return [[g[0][0], ':'.join(e[1] for e in g)] + g[0][2:]
for g in grouper(a_list)]
a_list = [
['1', '2', '3'],
['1', '1', '10', '11', '12'], # element added to test sorting
['1', '5', '6'],
['2', '8', '9', '8', '17'],
['2', '3', '5', '3'],
['1', '14', '89', '34', '15'],
]
print(combiner(a_list))
输出:
['1','1:2:5:14','10','11','12',['2','3:8','5','3']]
不确定您是否意识到了这一点,但通过使用简单的运算符。itemgetter(0,1))
您是在按字典顺序比较这些项目,而不是按它们的实际数字值。是的,也注意到了这一点,因为在本例中,排序列表中“14”位于“2”之前,在本例中,我可以接受,因为它实际上是字符串列表。还发现了一个名为的库,它以更“人性化”的方式进行排序。还发现,我不应该用'list'标识符命名列表,因为它内置于word:-)哇,我现在需要去阅读所有关于itertools的内容!谢谢