Bad_Coder
Bad_Coder

Reputation: 1019

Grouping two lists in python

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?

Upvotes: 2

Views: 2407

Answers (8)

hariK
hariK

Reputation: 3059

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']]

Upvotes: 0

wwii
wwii

Reputation: 23753

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']
>>>

Upvotes: 0

Epoch
Epoch

Reputation: 1

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.

Upvotes: 0

salmanwahed
salmanwahed

Reputation: 9647

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)]

Upvotes: 1

thefourtheye
thefourtheye

Reputation: 239473

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']]

Upvotes: 5

njzk2
njzk2

Reputation: 39397

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

Upvotes: 0

markcial
markcial

Reputation: 9323

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()]

Upvotes: 0

Shahriar
Shahriar

Reputation: 13804

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)

Upvotes: 0

Related Questions