2013-06-21 4 views
3

В списке списка 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}] 

    ] 

Мне нужно, чтобы получить самые высокие «Y» значения из каждого списка dicts ... поэтому результирующий список будет содержать:

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

В А, «х» является ключом каждого Dict в то время как «у» является значением каждого Dict.

Любые идеи? Спасибо.

+0

почему вы помечать этот NumPy? Кроме того, кортеж выглядит гораздо более быстрой структурой данных для использования, вы можете сохранить ясность словаря, если вы этого желаете, используя 'collections.namedtuple' – jamylak

ответ

6

max принимается дополнительно key параметр.

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

предложил - JF Себастьян:

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

brilliantt! :-) – user2480542

+2

или в виде списка: 'Z = [itemgetter (* 'xy') (max (lst, key = itemgetter ('y'))) для lst в A]' – jfs

+1

Это выглядит потрясающе. Для любого, кто задается вопросом: 'itemgetter (* 'xy')' равнозначен 'itemgetter ('x', 'y')' (я предпочитаю последнее для ясности, но это тоже выглядит хорошо) – jamylak

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

Я хотел бы использовать itemgetter и max «ы key аргумента:

from operator import itemgetter 

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

+1 Хороший! itemgetter doc: http://docs.python.org/2/library/operator.html#operator.itemgetter – gonz

2

подходит вам заявленная проблема , но я предлагаю изменить вашу базовую структуру данных. Кортежи намного быстрее для небольших элементов, таких как пункт. Вы можете сохранить ясность словаря, используя 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}] 

    ] 

Создание Point namedtuple просто

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

Это то, что экземпляр выглядит

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

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)]] 

Теперь работает как это гораздо проще:

>>> 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)] 

Чтобы сохранить преимущество скорости кортежей, лучше получить доступ по индексу:

>>> 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)] 
Смежные вопросы