0

I have a list that looks like this:

lst = [(1,'X1', 256),(1,'X2', 356),(2,'X3', 223)]

The first item of each tuple is an ID and I want to marge the items of each tuple where the ID is the same. For example I want the list to look like this:

lst = [(1,('X1','X2'),(256,356)),(2,'X3',223)

How do I do this the easiest way?

I have tried some solutions based on own logic but it did not work out.

Barmar
  • 741,623
  • 53
  • 500
  • 612
ILX
  • 1
  • 1
    Make a dictionary whose keys are the first element of the tuple, and values are lists of the other elements. – Barmar Nov 08 '22 at 20:59
  • Related: [How to group a list of tuples/objects by similar index/attribute in python?](/q/6602172/4518341) – wjandrea Nov 08 '22 at 21:06

2 Answers2

0

Use a dictionary whose keys are the IDs, so you can combine all the elements with the same ID.

from collections import defaultdict

lst = [(1,'X1', 256),(1,'X2', 356),(2,'X3', 223)]
result_dict = defaultdict(lambda: [[], []])

for id, item1, item2 in lst:
    result_dict[id][0].append(item1)
    result_dict[id][1].append(item2)

result = [(id, *map(tuple, vals)) for id, vals in result_dict.items()]
print(result)

Output is:

[(1, ('X1', 'X2'), (256, 356)), (2, ('X3',), (223,))]
Barmar
  • 741,623
  • 53
  • 500
  • 612
0

This can be done with a single-line list comprehension (after obtaining a set of ids), and for a general case of having multiple fields other than the id (and not just 2 other fields):

lst = [(1,'X1', 256),(1,'X2', 356),(2,'X3', 223)]

ids = {x[0] for x in lst} 
result = [(id, list(zip(*[x[1:] for x in lst if x[0] == id]))) for id in ids]
print(result)
# [(1, [('X1', 'X2'), (256, 356)]), (2, [('X3',), (223,)])]

So there's no need to go through a dictionary stage which is then turned into a list, and there's also no need to hardcode indexing of two elements and other such limitations.

ShlomiF
  • 2,686
  • 1
  • 14
  • 19