2013-06-21 61 views
3

的Python列表最高值在類型的字典列表的列表:選擇從類型的字典

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」值...這樣的結果列表將包含:

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

在A中,「x」爲各字典的鍵而「Y」是每個字典的值。

任何想法?謝謝。

+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')))for lst in 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

我會使用itemgettermaxkey說法:

from operator import itemgetter 

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

+1 Nice! itemgetter文檔: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)]