1

My problem, is that I have a nested list

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

and i wanted to merge those list that have a common index value also without sorting the resultant list. My prefered output:

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

I found the solution from here and here But the output im getting is somehow sorted, which it comes to my current output:

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

My code goes:

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)

I would appreciate the help in here, and im also open to new suggest on how to do this in an easier way, coz honestly the i havent use the union() nor intersection() methods before. thanx

Community
  • 1
  • 1
rockStar
  • 1,296
  • 12
  • 22

1 Answers1

4

You can use a dictionary with the first element of each list as the key and extend a list each time as they're encountered in the list-of-lists, eg:

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

Then we:

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

Optionally you can use d = collections.OrderedDict() here if it's completely necessary to guarantee the order of the keys is as seen in the list.

Which gives you a d of:

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

If you then want to unpack back to a lists of lists (although it's probably more useful being a dict) then you can do:

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

To get:

[['a', 'apple', 1, 'artichoke', 'antenna'],
 ['b', 'banana', 0, 'brocolli', 'baton'],
 ['c', None, 22]]
Jon Clements
  • 138,671
  • 33
  • 247
  • 280
  • thanx for the response, and i learned a new thing here coz i didnt know that you can actually do `for k, *vals in data:` where the first element of the list is k and the remaining values would be in `vals`. – rockStar Nov 10 '18 at 15:22
  • 1
    @rockStar it's fairly useful sometimes - you might want to check out: https://www.python.org/dev/peps/pep-3132/ – Jon Clements Nov 10 '18 at 15:29