Reputation: 57
I have a list of dict and i want to remove all objects with an equal x value keeping the y max value and the list order. I made the following code:
#!/usr/bin/python3
from pprint import pprint
import operator
lst = [{'x': 207, 'y': 40}, {'x': 207, 'y': 45}, {'x': 254, 'y': 62}, {'x': 260, 'y': 26}, {'x': 351, 'y': 71}, {'x': 351, 'y': 5}, {'x': 351, 'y': 15}, {'x': 391, 'y': 24}, {'x': 391, 'y': 48}]
pprint(lst)
[{'x': 207, 'y': 40},
{'x': 207, 'y': 45},
{'x': 254, 'y': 62},
{'x': 260, 'y': 26},
{'x': 351, 'y': 71},
{'x': 351, 'y': 5},
{'x': 351, 'y': 15},
{'x': 391, 'y': 24},
{'x': 391, 'y': 48}]
copy = []
[
copy.append(max(
(point2 for point2 in lst if point["x"] == point2["x"]),
key=operator.itemgetter('y'))
)
for point in lst
if next(
(cPoint for cPoint in copy if cPoint['x'] == point['x']),
None) == None
]
pprint(copy)
[{'x': 207, 'y': 45},
{'x': 254, 'y': 62},
{'x': 260, 'y': 26},
{'x': 351, 'y': 71},
{'x': 391, 'y': 48}]
I'm just asking if there is a more elegant (and Pythonic) way to do this?
Thanks in advance
Upvotes: 2
Views: 1060
Reputation: 18446
In addition to tobias_k's answer, here is one in a more functional style. First, we group all elements of lst
by their x
value, then, for each group, we get the one with the largest y
. Afterwards, we can just go though all elements of lst
and check if it's inside the list of maxima. If it is, put it into copy
:
import itertools
getx, gety = lambda a: a['x'], lambda a: a['y'] # or use operator.itemgetter
groups = itertools.groupby(sorted(lst, key=getx), key=getx)
m = [max(b, key=gety) for a,b in groups]
copy = [l for l in lst if l in m]
Upvotes: 2
Reputation: 82899
How about this: First create a dictionary holding the maximum y
value for each x
, then keep those values from the list that have that highest y
value for their respective x
.
maxima = {}
for d in lst:
x, y = d["x"], d["y"]
if x not in maxima or y > maxima[x]:
maxima[x] = y
copy = [d for d in lst if d["y"] == maxima[d["x"]]]
Upvotes: 2