简体   繁体   中英

How to merge internal lists of a 2D list in Python

I have a list of tuples in a 2D list, and I want to merge the list inside the tuples which correspond to the same integer.

For example:

list1 = [(0, [1]), (1, [0]), (1, [3]), (1, [9]), (2, [1]), (2, [4]), (3, [5]), (8, [1])]

I want to get the following output:

output = [(0, [1]), (1, [0,3,9]), (2,[1,4]), (3,[5]), (8,[1])]

I tried to use list comprehension but I didn't get the expected output. Could anyone help me get the output?

(I can't use dictionary)

Without dict / itertools - just nested loop

list1 = [(0, [1]), (1, [0]), (1, [3]), (1, [9]), (2, [1]), (2, [4]), (3, [5]), (8, [1])]
keys = keys = sorted({x[0] for x in list1})
lst = [(key,[]) for key in keys]
for e  in list1:
  for ee in lst:
    if ee[0] == e[0]:
      ee[1].append(e[1][0])
print(lst)

output

[(0, [1]), (1, [0, 3, 9]), (2, [1, 4]), (3, [5]), (8, [1])]

You could use a list comprehension with itertools :

from itertools import groupby, chain
[(k, list(chain.from_iterable((e[1] for e in g))))
 for k,g in groupby(list1, lambda x: x[0])]

NB. The code above assumes that the input is sorted on the first key of that the consecutive keys must be grouped together. If their is a chance that the keys are not sorted and they still must be merged, then add a sorting step: groupby(sorted(list1, lambda x: x[0]), lambda x: x[0])

output:

[(0, [1]), (1, [0, 3, 9]), (2, [1, 4]), (3, [5]), (8, [1])]

If data is sorted by first tuple element (the key) you can just iterate over source list and concatenate lists until key is the same. Code:

sorted_list = [
    (0, [1]), (1, [0]), (1, [3]), (1, [9]),
    (2, [1]), (2, [4]), (3, [5]), (8, [1])
]
lst = []
for i in sorted_list:
    if lst and lst[-1][0] == i[0]:
        lst[-1][1].extend(i[1])
    else:
        lst.append(i)

If your data is not sorted, you can sort it before. Code:

unsorted_list = [
    (8, [1]), (3, [5]), (2, [4]), (2, [1]),
    (1, [9]), (1, [3]), (1, [0]), (0, [1])
]
unsorted_list.sort()
lst = []
for i in unsorted_list:
    if lst and lst[-1][0] == i[0]:
        lst[-1][1].extend(i[1])
    else:
        lst.append(i)

Both variants will modify source list, but you can avoid it if you'll append a copy of element, not element itself. For sorted input code will be:

sorted_list = [
    (0, [1]), (1, [0]), (1, [3]), (1, [9]),
    (2, [1]), (2, [4]), (3, [5]), (8, [1])
]
lst = []
for k, l in sorted_list:
    if lst and lst[-1][0] == k:
        lst[-1][1].extend(l)
    else:
        lst.append((k, l[:]))

For unsorted input we can create a sorted copy of source list and work with it:

unsorted_list = [
    (8, [1]), (3, [5]), (2, [4]), (2, [1]),
    (1, [9]), (1, [3]), (1, [0]), (0, [1])
]
sorted_list = sorted(unsorted_list)
lst = []
for i in sorted_list:
    if lst and lst[-1][0] == i[0]:
        lst[-1][1].extend(i[1])
    else:
        lst.append(i)

This is the simplest solution and the fastest. Here is test results (lower is better) :

balderman(sorted_list): 1.780111159
balderman(unsorted_list): 1.7589877340000002
mozway(sorted_list): 1.0863068500000002
mozway_sort(unsorted_list): 1.2763536279999999
olvin(sorted_list): 0.5608128269999995
olvin_sort(unsorted_list): 0.6723953750000007
olvin_keep_source(sorted_list): 0.6709458179999999
olvin_sort_keep_source(unsorted_list): 0.7308210260000001

Code I've used for tests is here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM