合并具有公共元素值的列表而不进行排序

时间:2018-11-10 14:59:43

标签: python python-3.x list

我的问题是我有一个nested list

l = [
     ['a','apple',1],
     ['b', 'banana', 0], 
     ['a', 'artichoke', 'antenna'], 
     ['b', 'brocolli', 'baton'],
     ['c', None, 22]
    ]

,我也想合并具有共同索引值的list而不对结果列表进行排序。 我的首选输出:

[
 ['a','apple', 1, 'artichoke', 'antenna'],
 ['b', 'banana', 0, 'brocolli', 'baton'],
 ['c', None, 22]
]

我从herehere找到了解决方案 但是即时获取的输出是以某种方式排序的,它涉及到我当前的输出:

[['c', None, 22], [1, 'antenna', 'apple', 'artichoke', 'a'], [0, 'b', 'banana', 'brocolli', 'baton']]

我的代码去了

len_l = len(l)
i = 0
while i < (len_l - 1):
    for j in range(i + 1, len_l):

        # i,j iterate over all pairs of l's elements including new 
        # elements from merged pairs. We use len_l because len(l)
        # may change as we iterate
        i_set = set(l[i])
        j_set = set(l[j])
        if len(i_set.intersection(j_set)) > 0:
            # Remove these two from list
            l.pop(j)
            l.pop(i)

            # Merge them and append to the orig. list
            ij_union = list(i_set.union(j_set))
            l.append(ij_union)


            # len(l) has changed
            len_l -= 1

            # adjust 'i' because elements shifted
            i -= 1

            # abort inner loop, continue with next l[i]
            break
    i += 1
print(l)

我希望在此提供帮助,我也欢迎就如何以更简单的方式进行操作提出新的建议,说实话,我以前没有使用过union()intersection()方法。 谢谢

1 个答案:

答案 0 :(得分:4)

您可以使用将每个列表的第一个元素作为关键字的字典,并在每次在列表列表中遇到它们时扩展列表,例如:

data = [
    ['a','apple',1],
    ['b', 'banana', 0], 
    ['a', 'artichoke', 'antenna'], 
    ['b', 'brocolli', 'baton'],
    ['c', None, 22]
]

然后我们:

d = {} 
for k, *vals in data:
    d.setdefault(k, []).extend(vals)

如果完全有必要确保键的顺序如列表中所示,则可以在此处使用d = collections.OrderedDict()

其中d的给您以下内容:

{'a': ['apple', 1, 'artichoke', 'antenna'],
 'b': ['banana', 0, 'brocolli', 'baton'],
 'c': [None, 22]}

如果您随后想拆开列表列表(尽管使用dict可能更有用),则可以执行以下操作:

new_data = [[k, *v] for k, v in d.items()]

获得:

[['a', 'apple', 1, 'artichoke', 'antenna'],
 ['b', 'banana', 0, 'brocolli', 'baton'],
 ['c', None, 22]]