Arnab
Arnab

Reputation: 1037

Grouping elements in a list of lists

I have a few records which reads as follows:

list1= [['corner grant and main reef road, new state area, springs', 'springs'],
     ['corner grant and main reef road, new state area, springs', 'palm springs'],
     ['corner grant and main reef road, new state area, springs', 'edenvale']]

I want my record to look like this:

list2= ['corner grant and main reef road, new state area, springs', 'springs | palm springs | edenvale']

I wrote the following code to accomplish this:

for i in range(len(list1)-1):
    if list1[i][0] == list1[i+1][0]:
        list2.append([list1[i][0], list1[i][1] + "|" + list1[i + 1][1]])
    else:
        pass

This works if I have two elements in a list and are consecutive entries, it however fails if there are more than 2 items and are not consecutive. Could anyone please point out a suitable way to accomplish this.

Upvotes: 2

Views: 3534

Answers (3)

Alex Fung
Alex Fung

Reputation: 2006

You can use a dict for grouping.

To make things easier defaultdict is a good sub-class of dict for this case:

from collections import defaultdict
list1= [['corner grant and main reef road, new state area, springs', 'springs'],
     ['corner grant and main reef road, new state area, springs', 'palm springs'],
     ['corner grant and main reef road, new state area, springs', 'edenvale']]

def grouping(l):
    d = defaultdict(list)
    for key,value in l:
        d[key].append(value)
    for key in d:
        d[key] = ' | '.join(d[key])
    return list(d.items())
list2 = grouping(list1)
print(list2)

Output:

[('corner grant and main reef road, new state area, springs', 'springs | palm springs | edenvale')]

Testing:

list3= [['corner grant and main reef road, new state area, springs', 'springs'],
        ['corner grant and main reef road, new state area, springs', 'palm springs'],
        ['corner grant and main reef road, new state area, springs', 'edenvale'],
        ['testing 1243','hi'],
        ['corner grant and main reef road, new state area, springs', '123456'],
       ]
print(grouping(list3)

Output:

[('corner grant and main reef road, new state area, springs', 'springs | palm springs | edenvale | 123456'), ('testing 1243', 'hi')]

If you need to preserve the order, use OrderedDict instead:

from collections import OrderedDict
def grouping(l):
    d = OrderedDict()
    for key,value in l:
        d.setdefault(key, []).append(value)
    for key in d:
        d[key] = ' | '.join(d[key])
    return list(d.items())

Upvotes: 5

Praveen
Praveen

Reputation: 9335

You can use groupby funciton to group the elements in the list.

try;

from itertools import groupby
list1 = ....

grp = groupby(sorted(list1, key=lambda x: x[0]), lambda x: x[0])
list2 = [(key, " | ".join([x for _, x in group])) for key, group in grp]

Upvotes: 2

hurturk
hurturk

Reputation: 5454

Inspired from this answer, adapted for your case with preserved order:

list1 = [['corner grant and main reef road, new state area, springs', 'springs'],
     ['corner grant and main reef road, new state area, springs', 'palm springs'],
     ['corner grant and main reef road, new state area, springs', 'edenvale']]

from itertools import groupby
from operator import itemgetter

list2 = []
for _, v in groupby(sorted(list1, key=itemgetter(0)), key=itemgetter(0)):
    v = list(v)   
    cols = " | ".join([sub[1] for sub in v])
    list2.append([v[0][0], cols])

print(list2)

output:

[['corner grant and main reef road, new state area, springs', 'springs | palm springs | edenvale']]

Upvotes: 2

Related Questions