【问题标题】:python join list of list of lists using keypython使用键加入列表列表的列表
【发布时间】:2018-03-15 22:00:22
【问题描述】:

我有这个列表结构:

lst = [[['a', 100],['b', 200],['d', 325]],[['a', 50],['b', 250],['c', 75]]]

'lst' 可以包含任意数量的子列表(len(lst) 可以大于 2)

作为我想要的输出:

output = [['a',100,50],['b',200,250],['c',0,75],['d',325,0]]

这是另一个例子:

lst = [[['a', 100],['b', 200],['d', 325]],[['a', 50],['b', 250],['c', 75]], [['a', 22], ['b', 10]]]

output = [['a', 100, 50, 22],['b', 200, 250, 10], ['c', 0, 75, 0], ['d', 325, 0, 0]]

你会怎么做?

【问题讨论】:

  • 为什么有些项目应该包含零,比如['c',0,75]
  • lst 是否总是具有这种结构? IOW,它会一直是((两个项目列表)的列表)的列表吗?
  • @RomanPerekhrest 会出现是因为第一个子列表不包含c“key”,所以 OP 希望它默认为 0
  • @Wondercricket,你能保证吗?
  • @Wondercricket 是的,就是这样

标签: python list merge


【解决方案1】:

您可以使用defaultdict

from collections import defaultdict
import itertools
d = defaultdict(list)
lst = [[['a', 100],['b', 200],['d', 325]],[['a', 50],['b', 250],['c', 75]]]
for a, b in itertools.chain.from_iterable(lst):
   d[a].append(b)

new_lst = sorted([list(itertools.chain.from_iterable([[a], [0 for i in range(len(max(d.items(), key=lambda x:len(x[-1])))-len(b))]+b])) for a, b in d.items()])

输出:

[['a', 100, 50], ['b', 200, 250], ['c', 0, 75], ['d', 0, 325]]

【讨论】:

  • thx @Ajax1234 您的解决方案适用于两个子列表的列表,但有两个以上的子列表,例如 [[['a', 100],['b', 200],['d' , 325]],[['a', 50],['b', 250],['c', 75]], [['a', 22], ['b': 10]]]得到输出: [['a', 100, 50, 22], ['b', 200, 250, 10], ['c', 0, 75], ['d', 0, 325]] 它应该是 [['a', 100, 50, 22],['b', 200, 250, 10], ['c', 0, 75, 0], ['d', 325, 0, 0] ]
【解决方案2】:

如果我们有一个lst 中使用的所有字母键的列表,这个任务会简单一些,但是提取它们很容易。

我的策略是将子列表转换为字典。这使得获取与每个键关联的值变得容易且高效。 dict.get 方法允许我们为丢失的键提供默认值。

lst = [[['a', 100],['b', 200],['d', 325]],[['a', 50],['b', 250],['c', 75]]]

# Convert outer sublists to dictionaries
dicts = [*map(dict, lst)]

# Get all the keys
keys = set()
for d in dicts:
    keys.update(d.keys())

# Get data for each key from each dict, using 0 if a key is missing
final = [[k] + [d.get(k, 0) for d in dicts] for k in sorted(keys)]
print(final)

输出

[['a', 100, 50], ['b', 200, 250], ['c', 0, 75], ['d', 325, 0]]

如果我们使用

lst = [[['a', 100],['b', 200],['d', 325]],[['a', 50],['b', 250],['c', 75]], [['a', 22], ['b', 10]]]

那么输出是

[['a', 100, 50, 22], ['b', 200, 250, 10], ['c', 0, 75, 0], ['d', 325, 0, 0]]

如果您想在 Python 2 上运行它,您需要对将外部子列表转换为字典的代码进行细微更改。改成

dicts = list(map(dict, lst))

这在 Python 2 和 3 上都可以正常工作。如果你只需要在 Python 2 上运行它,你可以简单地做

dicts = map(dict, lst)

因为map 在 Python 2 中返回一个列表,而不是一个迭代器。

【讨论】:

  • 很好的答案,但值得一提的是,这是一个 Python 3.5
  • @Wondercricket SO Python 社区的政策是假设 Python 3,除非明确声明了 Python 2。 ;) 但我会在我的答案中添加一些相关信息。
  • 好东西,但是,是的......我实际上是在 Python 2.x 上,切换会非常痛苦,因为我使用的其他一些东西依赖于它
【解决方案3】:

带有itertools.chain.from_iterable()itertools.groupby()函数和内置next()函数:

import itertools

lst = [ [['a', 100],['b', 200],['d', 325]],[['a', 50],['b', 250],['c', 75]], [['a', 22], ['b', 10]] ]
lst_len = len(lst)
sub_keys = [{k[0] for k in _} for _ in lst]
result = [[k] + [next(g)[1] if k in sub_keys[i] else 0 for i in range(lst_len)]
          for k,g in itertools.groupby(sorted(itertools.chain.from_iterable(lst), key=lambda x:x[0]), key=lambda x: x[0])]

print(result)

输出:

[['a', 100, 50, 22], ['b', 200, 250, 10], ['c', 0, 75, 0], ['d', 325, 0, 0]]

【讨论】:

  • @PM2Ring,为更大的列表添加了设置
【解决方案4】:

这是我的“长期”方法,我只需要弄清楚发生了什么:

lst = [[['a', 100],['b', 200],['d', 325]],
      [['a', 50],['b', 250],['c', 75]],
      [['a', 22], ['b', 10]],
      [['c', 110],['f', 200],['g', 425]],
      [['a', 50],['f', 250],['h', 75]],
      [['a', 32], ['b', 10]], ]
nlist = []
store={}
for n,j in enumerate(lst):
    for i in j  :
        if i[0] in store :
            store[i[0]].append(i[1])
        else :
            store[i[0]] = nlist + [i[1]]
    nlist += [0]
    for k,v in store.items() :
        if len(v) < n+1 :
            store[k] = v + [0]
print(store)
result=[]
for k,v in store.items():
    result += [[k] + v]
print(sorted(result))

【讨论】:

    猜你喜欢
    • 2015-10-07
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    • 2017-02-07
    • 2020-03-27
    • 2015-06-05
    • 2022-01-19
    • 2021-06-17
    相关资源
    最近更新 更多