在Python中垂直展平列表列表

时间:2013-10-17 14:49:05

标签: python

输入

a = [
        [1, 'abc', '123'],
        [1, 'def', '456'],
        [2, 'ghi', '789'],
        [2, 'jkl', '012'],
        [2, 'mno', '345'],
        [3, 'pqr', '678']
    ]

在下面获得所需输出的最佳方法是什么?请记住输入列表a将是巨大的(~100K)。

输出

a = [
        [1, 'abc;def', '123;456'],
        [2, 'ghi;jkl;mno', '789;012;345'],
        [3, 'pqr', '678']
    ]

注意:

  • 元素基于Column1进行分组。
  • 元素顺序并不重要(可以按任何顺序排列)。
  • 然后,任何后续列都由分隔符;连接。
  • 禁止第一列,所有其他列都是字符串字段。

3 个答案:

答案 0 :(得分:1)

我不了解性能,但我可能会使用itertools.groupby并执行类似[编辑以使每个子列表成为一个平面列表]的内容:

>>> from itertools import groupby
>>> from operator import itemgetter
>>> [[k] + [';'.join(v) for v in zip(*g)[1:]] for k,g in groupby(a, itemgetter(0))]
[[1, 'abc;def', '123;456'], [2, 'ghi;jkl;mno', '789;012;345'], [3, 'pqr', '678']]

这假定列表在子列表的第一个元素中是连续的。如果没有,那么您需要将groupby替换为

groupby(sorted(a, key=itemgetter(0)), itemgetter(0))

代替。

以上使用了一些技巧:

  1. groupby,它通过键函数的值对可迭代中的连续元素进行分组
  2. itemgetter,它基本上可以快速获取元素:itemgetter(0)基本上是快速lambda x: x[0]
  3. zip(*g),这是通过组合zip*元组解包来转置事物的常用习惯用法:zip(*([1,2],[3,4])) == [(1, 3), (2, 4)]。 (在Python 2中,无论如何,在3中你需要使它成为list(zip(..))。)

答案 1 :(得分:1)

from collections import defaultdict

a = [
        [1, 'abc', '123'],
        [1, 'def', '456'],
        [2, 'ghi', '789'],
        [2, 'jkl', '012'],
        [2, 'mno', '345'],
        [3, 'pqr', '678']
    ]

dd = defaultdict(lambda: [[], []])

for key, s0, s1 in a:
    dd[key][0].append(s0)
    dd[key][1].append(s1)

a = [[key, ';'.join(dd[key][0]), ';'.join(dd[key][1])] for key in dd]

for elem in a:
    print elem

输出:

[1, 'abc;def', '123;456']
[2, 'ghi;jkl;mno', '789;012;345']
[3, 'pqr', '678']

答案 2 :(得分:0)

这是我迄今为止所能得到的,如果有人可以在这段代码上抛出一些代码,那就太棒了:

a = [
        [1, 'abc', '123'],
        [1, 'def', '456'],
        [2, 'ghi', '789'],
        [2, 'jkl', '012'],
        [2, 'mno', '345'],
        [3, 'pqr', '678']
    ]
    count = 2
    index = 1
    prev_val = a[index][0]
    output = []
    first_ele = a[0]

while index < len(a)+1:
    if prev_val == count:
        output[first_ele][1] += ';' + a[index][1] + str(a[index][2])
    else:
        count += 1
        index += 1`