如何在Python中合并多个列表

1 投票
3 回答
3587 浏览
提问于 2025-04-16 12:53

我有多个列表,像下面这样:

[u'a', 11, u'P']
[u'a', 11, u'A']
[u'b', 2, u'P']
[u'c', 1, u'P']
[u'c', 2, u'P']
[u'd', 1, u'P']
[u'e', 3, u'P']
[u'f', 2, u'P']
[u'a', 1, u'P']
[u'a', 2, u'P']
[u'b', 1, u'P']
[u'b', 11, u'P']

我想知道怎么把这些列表合并在一起,然后循环这个列表,把它们加起来,像下面这样:

[u'a', 11, u'P'] + [u'a', 2, u'P'] + [u'a', 11, u'A'] = ['a',('P' : 13) ,('A': 11)]

[u'b', 2, u'P'] + [u'b', 1, u'P'] + [u'b', 11, u'P'] = ['b',14,p]

输出应该像下面这样:

['a',('P' : 13) ,('A': 11)]
['b',14,'p']

3 个回答

1

如果你使用itertools里的groupby,这个问题可以用一行代码解决。

把所有的列表放到一个大列表里,叫做lst。

lst = [
    [u'a', 11, u'P']
    [u'a', 11, u'A']
    [u'b', 2, u'P']
    [u'c', 1, u'P']
    [u'c', 2, u'P']
    [u'd', 1, u'P']
    [u'e', 3, u'P']
    [u'f', 2, u'P']
    [u'a', 1, u'P']
    [u'a', 2, u'P']
    [u'b', 1, u'P']
    [u'b', 11, u'P']
]

然后在外层用groupby来对a、b、c等进行分组,再在每个分组内对第三个元素,比如P、A等进行再次分组。接着,把进一步分组的数据进行求和。

这里是解决方案:

from itertools import groupby
result = dict(
                ( k, dict( (k1, sum([i[1] for i in g2])) for k1, g2 in groupby(g, key=lambda y: y[2] ) ) )
                for k, g in groupby(lst, key=lambda x: x[0])
            )

为了更好地理解,我建议你先试试单层的groupby,然后再去了解嵌套的groupby。

这里有几个链接可以参考:

http://docs.python.org/library/itertools.html#itertools.groupby

http://www.builderau.com.au/program/python/soa/Python-groupby-the-iterator-swiss-army-knife/0,2000064084,339280431,00.htm

2

你可以考虑使用 collections.defaultdict,然后遍历这些字典列表中的值。

import collections
d = collections.defaultdict(list)
l = [[u'a', 11, u'P'],[u'a', 11, u'A'],[u'a', 3, u'P'],[u'b', 2, u'P'],[u'c', 1, u'P'],[u'c', 2, u'P'],[u'd', 1, u'P'],[u'e', 3, u'P']]
for k1, v, k2 in l:
    if k1 in d:
            d[k1].append({k2:v})
    else: 
        d[k1] = [{k2:v}]

newdict = {}
for key,value in d.items():
    newvalue = {}
    for valuedict in value:
        for key2,value2 in valuedict.items():
            if key2 in newvalue:
                newvalue[key2] += value2
            else:
                newvalue[key2] = value2
    newdict[key] = newvalue

print newdict

这样你就能得到

{u'a': {u'A': 11, u'P': 14}, u'c': {u'P': 3}, u'b': {u'P': 2}, u'e': {u'P': 3}, u'd': {u'P': 1}}
1

你想要的输出看起来有点奇怪,因为两种情况之间不一致。其实你可以很简单地修改这个例子,得到你想要的任何输出:

lists = [
 [u'a', 11, u'P'],
 [u'a', 11, u'A'],
 [u'b', 2, u'P'],
 [u'c', 1, u'P'],
 [u'c', 2, u'P'],
 [u'd', 1, u'P'],
 [u'e', 3, u'P'],
 [u'f', 2, u'P'],
 [u'a', 1, u'P'],
 [u'a', 2, u'P'],
 [u'b', 1, u'P'],
 [u'b', 11, u'P']]

# Each key in this dictionary will be one of the first elements
# from the lists shown above.  The values will be dictionaries
# mapping a letter (one of the third elements in each list) to
# their total count (i.e. the sum of the second elements matching
# the other two columns)
from collections import defaultdict
results = defaultdict(dict)

for main_key, count, subkey in lists:
    d = results[main_key]
    d[subkey] = d.get(subkey,0) + count

for main_key, values in results.items():
    print main_key, "=>", values

输出结果是:

a => {u'A': 11, u'P': 14}
c => {u'P': 3}
b => {u'P': 14}
e => {u'P': 3}
d => {u'P': 1}
f => {u'P': 2}

更新:感谢 sharjeel 在下面的评论中建议我用 defaultdict 替代 setdefault


更新 2:在你下面评论中的进一步提问中,你提到你想要的输出是 "[a] 的列表集合,像 [[u'a', 11, u'P'], [u'a', 11, u'A']"。 (我暂时假设你是指一个列表的列表,而不是集合,但这几乎一样简单。)为了构建这样的列表列表,你可以用以下代码替换打印值的循环:

lists_output = []

for main_key, values in results.items():
    for subkey, count in values.items():
       lists_output.append([main_key,count,subkey])

print lists_output

... 这将给出以下输出:

[[u'a', 11, u'A'], [u'a', 14, u'P'], [u'c', 3, u'P'], [u'b', 14, u'P'], [u'e', 3, u'P'],
 [u'd', 1, u'P'], [u'f', 2, u'P']]

撰写回答