2

I have two lists which I want to group on the basis of the first element of the lists.

list1 = [['1','abc','zef'],['2','qwerty','opo'],['3','lol','pop']]

list2 = [['1','rofl','pole'],['2','sole','pop'],['3','lmao','wtf']]

Here the first elements in the list inside the list are '1' , '2' and '3'.

I want my final list to be like :-

Final_List = [['1', 'abc', 'zef', 'rofl', 'pole'], ['3', 'lol', 'pop', 'lmao', 'wtf'], ['2', 'qwerty', 'opo', 'sole', 'pop']]

I have tried this using below code.

#!/usr/bin/python
list1 = [['1','abc','zef'],['2','qwerty','opo'],['3','lol','pop']]
list2 = [['1','rofl','pole'],['2','sole','pop'],['3','lmao','wtf']]
d = {}
for i in list1:
    d[i[0]] = i[1:]
for i in list2:
    d[i[0]].extend(i[1:])
Final_List = []
for key, value in d.iteritems():
    value.insert(0,key)
   Final_List.append(value)

This code works but i was wondering if there was an easy and cleaner way to do it

Any help?

5
  • are the first two elements always the exact same side by side like your example? Commented Dec 18, 2014 at 14:40
  • your data structure is strange. why is there what appears to be an index or a key as the first element of each list item? Commented Dec 18, 2014 at 14:42
  • 1
    Questions like this may be better suited for Code Review. Commented Dec 18, 2014 at 14:42
  • the way you do it using by changing the data structure using dicts is way cleaner than what is suggested in the posted answers. Commented Dec 18, 2014 at 14:43
  • the thing you can shorten in your version is using list comprehensions Commented Dec 18, 2014 at 14:44

8 Answers 8

5

I would have written like you have written with a little modification, like this

  1. Prepare a dictionary with all the elements from the second position gathered corresponding to the first element.

    d = {}
    for items in (list1, list2):
        for item in items:
            d.setdefault(item[0], [item[0]]).extend(item[1:])
    
  2. And then just get all the values from the dictionary (Thanks @jamylak) :-)

    print(d.values())
    

Output

[['3', 'lol', 'pop', 'lmao', 'wtf'],
 ['1', 'abc', 'zef', 'rofl', 'pole'],
 ['2', 'qwerty', 'opo', 'sole', 'pop']]
Sign up to request clarification or add additional context in comments.

2 Comments

I would love to hear how I can improve this post.
I didn't downvote but one improvement is d.setdefault(item[0], [item[0]]).extend(item[1:]) and then to get the list all it is, is d.values()
1

If item sequence in the lists inside of the Final_List is not important then this can be used,

[list(set(sum(itm, []))) for itm in zip(list1, list2)]

Comments

0

Your code seems correct. Just modify the following portion:

Final_List = []    
for key in d:
    L = [key] + [x for x in d[key]]
    Final_List.append(L)

Comments

0

Yes, with list comprehension and enumerate

list1 = [['1','abc','zef'],['2','qwerty','opo'],['3','lol','pop']]

list2 = [['1','rofl','pole'],['2','sole','pop'],['3','lmao','wtf']]

print [set(v + list2[k]) for k,v in enumerate(list1)]

[['1', 'abc', 'zef', 'rofl', 'pole'], ['2', 'qwerty', 'opo', 'sole', 'pop'], ['3', 'lol', 'pop', 'lmao', 'wtf']]

EDIT

With index relation

list1 = [['1','abc','zef'],['2','qwerty','opo'],['3','lol','pop']]
list2 = [['1','rofl','pole'],['3','lmao','wtf'],['2','sole','pop']]

d1 = {a[0]:a for a in list1}
d2 = {a[0]:a for a in list2}
print [set(v + d2[k]) for k, v in d1.items()]

Comments

0

Using default dict and list comprehensions you can shorten your code

from collections import defaultdict

list1 = [['1','abc','zef'],['2','qwerty','opo'],['3','lol','pop']]
list2 = [['1','rofl','pole'],['2','sole','pop'],['3','lmao','wtf']]

d = defaultdict(list)

for i in list1 + list2:
    d[i[0]].extend(i[1:])

Final_List = [[key] + value for key, value in d.iteritems()]

print Final_List

Comments

0
list3 = []
for i in xrange(0,max(len(list1[0]), len(list2[0]))):
    list3.append(list(list1[i]))
    list3[i].extend(x for x in list2[i] if x not in list3[i])

with a xrange, you can iterate only once through the list.

Comments

0

A bit of functional style:

import operator, itertools
from pprint import pprint
one = [['1','abc','zef'],['2','qwerty','opo'],['3','lol','pop']]
two = [['1','rofl','pole'],['2','sole','pop'],['3','lmao','wtf']]

A few helpers:

zero = operator.itemgetter(0)
all_but_the_first = operator.itemgetter(slice(1, None))
data = (one, two)

def foo(group):
    # group is (key, iterator) from itertools.groupby
    key = group[0]
    lists = group[1]
    result = list(key)
    for item in lists:
        result.extend(all_but_the_first(item))
    return result

Function to process the daa

def process(data, func = foo):
    # concatenate all the sublists
    new = itertools.chain(*data)
    # group by item zero
    three = sorted(new, key = zero)
    groups = itertools.groupby(three, zero)
    # iterator that builds the new lists
    return itertools.imap(foo, groups)

Usage

>>> pprint(list(process(data)))

[['1', 'abc', 'zef', 'rofl', 'pole'],
 ['2', 'qwerty', 'opo', 'sole', 'pop'],
 ['3', 'lol', 'pop', 'lmao', 'wtf']]
>>>
>>> for thing in process(data):
    print thing

['1', 'abc', 'zef', 'rofl', 'pole']
['2', 'qwerty', 'opo', 'sole', 'pop']
['3', 'lol', 'pop', 'lmao', 'wtf']
>>>

Comments

0

list1 = [['1','abc','zef'],['2','qwerty','opo'],['3','lol','pop']]

list2 = [['1','rofl','pole'],['2','sole','pop'],['3','lmao','wtf']]

Final_List = []

for i in range(0, len(list1)):

    Final_List.append(list1[i] + list2[i])

    del Final_List[i][3]

print Final_List

Output

[['1', 'abc', 'zef', 'rofl', 'pole'], ['2', 'qwerty', 'opo', 'sole', 'pop'], ['3', 'lol', 'pop', 'lmao', 'wtf']]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.