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.
CodePudding user response:
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,))]
CodePudding user response:
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.