从python的dicts列表中选择最高值

时间:2022-02-18 18:05:48

In a list of list of dicts:

在一系列dicts列表中:

 A = [
       [{'x': 1, 'y': 0}, {'x': 2, 'y': 3}, {'x': 3, 'y': 4}, {'x': 4, 'y': 7}],

       [{'x': 1, 'y': 0}, {'x': 2, 'y': 2}, {'x': 3, 'y': 13}, {'x': 4, 'y': 0}],

       [{'x': 1, 'y': 20}, {'x': 2, 'y': 4}, {'x': 3, 'y': 0}, {'x': 4, 'y': 8}]

     ]

I need to retrieve the highest 'y' values from each of the list of dicts...so the resulting list would contain:

我需要从每个dicts列表中检索最高的'y'值...所以结果列表将包含:

 Z = [(4, 7), (3,13), (1,20)]

In A, the 'x' is the key of each dict while 'y' is the value of each dict.

在A中,'x'是每个字典的关键,而'y'是每个字典的值。

Any ideas? Thank you.

有任何想法吗?谢谢。

4 个解决方案

#1


6  

max accept optional key parameter.

max accept可选键参数。

A = [
    [{'x': 1, 'y': 0}, {'x': 2, 'y': 3}, {'x': 3, 'y': 4}, {'x': 4, 'y': 7}],
    [{'x': 1, 'y': 0}, {'x': 2, 'y': 2}, {'x': 3, 'y': 13}, {'x': 4, 'y': 0}],
    [{'x': 1, 'y': 20}, {'x': 2, 'y': 4}, {'x': 3, 'y': 0}, {'x': 4, 'y': 8}]
]

Z = []
for a in A:
    d = max(a, key=lambda d: d['y'])
    Z.append((d['x'], d['y']))
print Z

UPDATE

UPDATE

suggested by – J.F. Sebastian:

建议 - J.F. Sebastian:

from operator import itemgetter
Z = [itemgetter(*'xy')(max(lst, key=itemgetter('y'))) for lst in A]

#2


5  

I'd use itemgetter and max's key argument:

我使用itemgetter和max的关键参数:

from operator import itemgetter

pair_getter = itemgetter('x', 'y')
[pair_getter(max(d, key=itemgetter('y'))) for d in A]

#3


4  

[max(((d['x'], d['y']) for d in l), key=lambda t: t[1]) for l in A]

#4


2  

The solution to your stated problem has been given, but I suggest changing your underlying data structure. Tuples are much faster for small elements such as a point. You may retain the clarity of a dictionary by using namedtuple if you so desire.

已经给出了所述问题的解决方案,但我建议更改您的基础数据结构。对于诸如点之类的小元素,元组要快得多。如果您愿意,可以使用namedtuple保留字典的清晰度。

>>> from collections import namedtuple
>>> A = [
       [{'x': 1, 'y': 0}, {'x': 2, 'y': 3}, {'x': 3, 'y': 4}, {'x': 4, 'y': 7}],

       [{'x': 1, 'y': 0}, {'x': 2, 'y': 2}, {'x': 3, 'y': 13}, {'x': 4, 'y': 0}],

       [{'x': 1, 'y': 20}, {'x': 2, 'y': 4}, {'x': 3, 'y': 0}, {'x': 4, 'y': 8}]

     ]

Making a Point namedtuple is simple

制作一个名为littletuple的点很简单

>>> Point = namedtuple('Point', 'x y')

This is what an instance looks like

这是一个实例的样子

>>> Point(x=1, y=0) # Point(1, 0) also works
Point(x=1, y=0)

A would then look like this

那么A会是这样的

>>> A = [[Point(**y) for y in x] for x in A]
>>> A
[[Point(x=1, y=0), Point(x=2, y=3), Point(x=3, y=4), Point(x=4, y=7)], 
 [Point(x=1, y=0), Point(x=2, y=2), Point(x=3, y=13), Point(x=4, y=0)], 
 [Point(x=1, y=20), Point(x=2, y=4), Point(x=3, y=0), Point(x=4, y=8)]]

Now working like this is much easier:

现在这样工作要容易得多:

>>> from operator import attrgetter
>>> [max(row, key=attrgetter('y')) for row in A]
[Point(x=4, y=7), Point(x=3, y=13), Point(x=1, y=20)]

To retain the speed advantages of tuples it's better to access by index:

要保留元组的速度优势,最好通过索引访问:

>>> from operator import itemgetter
>>> [max(row, key=itemgetter(2)) for row in A]
[Point(x=4, y=7), Point(x=3, y=13), Point(x=1, y=20)]

#1


6  

max accept optional key parameter.

max accept可选键参数。

A = [
    [{'x': 1, 'y': 0}, {'x': 2, 'y': 3}, {'x': 3, 'y': 4}, {'x': 4, 'y': 7}],
    [{'x': 1, 'y': 0}, {'x': 2, 'y': 2}, {'x': 3, 'y': 13}, {'x': 4, 'y': 0}],
    [{'x': 1, 'y': 20}, {'x': 2, 'y': 4}, {'x': 3, 'y': 0}, {'x': 4, 'y': 8}]
]

Z = []
for a in A:
    d = max(a, key=lambda d: d['y'])
    Z.append((d['x'], d['y']))
print Z

UPDATE

UPDATE

suggested by – J.F. Sebastian:

建议 - J.F. Sebastian:

from operator import itemgetter
Z = [itemgetter(*'xy')(max(lst, key=itemgetter('y'))) for lst in A]

#2


5  

I'd use itemgetter and max's key argument:

我使用itemgetter和max的关键参数:

from operator import itemgetter

pair_getter = itemgetter('x', 'y')
[pair_getter(max(d, key=itemgetter('y'))) for d in A]

#3


4  

[max(((d['x'], d['y']) for d in l), key=lambda t: t[1]) for l in A]

#4


2  

The solution to your stated problem has been given, but I suggest changing your underlying data structure. Tuples are much faster for small elements such as a point. You may retain the clarity of a dictionary by using namedtuple if you so desire.

已经给出了所述问题的解决方案,但我建议更改您的基础数据结构。对于诸如点之类的小元素,元组要快得多。如果您愿意,可以使用namedtuple保留字典的清晰度。

>>> from collections import namedtuple
>>> A = [
       [{'x': 1, 'y': 0}, {'x': 2, 'y': 3}, {'x': 3, 'y': 4}, {'x': 4, 'y': 7}],

       [{'x': 1, 'y': 0}, {'x': 2, 'y': 2}, {'x': 3, 'y': 13}, {'x': 4, 'y': 0}],

       [{'x': 1, 'y': 20}, {'x': 2, 'y': 4}, {'x': 3, 'y': 0}, {'x': 4, 'y': 8}]

     ]

Making a Point namedtuple is simple

制作一个名为littletuple的点很简单

>>> Point = namedtuple('Point', 'x y')

This is what an instance looks like

这是一个实例的样子

>>> Point(x=1, y=0) # Point(1, 0) also works
Point(x=1, y=0)

A would then look like this

那么A会是这样的

>>> A = [[Point(**y) for y in x] for x in A]
>>> A
[[Point(x=1, y=0), Point(x=2, y=3), Point(x=3, y=4), Point(x=4, y=7)], 
 [Point(x=1, y=0), Point(x=2, y=2), Point(x=3, y=13), Point(x=4, y=0)], 
 [Point(x=1, y=20), Point(x=2, y=4), Point(x=3, y=0), Point(x=4, y=8)]]

Now working like this is much easier:

现在这样工作要容易得多:

>>> from operator import attrgetter
>>> [max(row, key=attrgetter('y')) for row in A]
[Point(x=4, y=7), Point(x=3, y=13), Point(x=1, y=20)]

To retain the speed advantages of tuples it's better to access by index:

要保留元组的速度优势,最好通过索引访问:

>>> from operator import itemgetter
>>> [max(row, key=itemgetter(2)) for row in A]
[Point(x=4, y=7), Point(x=3, y=13), Point(x=1, y=20)]