按值列出组列表并保留两者

时间:2015-03-03 18:55:29

标签: python

我有一个列表,其中包含元组对的xy点(作为元组)。第一个表示任意点,第二个表示群集的质心,该群集是该点的最近邻居。

all_neighbours = 
[((28, 145), (25, 125)), ((65, 140), (44, 105)), ((50, 130), (25, 125)), 
 ((38, 115), (44, 105)), ((55, 118), (44, 105)), ((50, 90),  (44, 105)), 
 ((63, 88 ), (44, 105)), ((43, 83 ), (29, 97 )), ((50, 60),  (55, 63 )),
 ((50, 30 ), (55, 20 ))]

我想创建一个新列表,其中包含由这些点最近邻居元组创建的新neigbourhoud / cluster。类似的东西(或者有元组而不是列表):

[[(55, 20), (50, 30)], [(25, 125), (28, 145), (50, 130)], 
 [(44, 105), (65, 140), (38, 115), (55, 118), (50, 90), (63, 88)],
 [(55, 63), (50, 60)], [(29, 97),  (43, 83)]]

我试过这样做:

centroids = set(map(lambda x: x[1], all_neighbours))
neighbourhood = [(x, [y[0] for y in all_neighbours if y[1] == x]) for x in centroids]
>>
[((55, 20), [(50, 30)]), ((25, 125), [(28, 145), (50, 130)]),
 ((44, 105), [(65, 140), (38, 115), (55, 118), (50, 90), (63, 88)]),
 ((55, 63), [(50, 60)]), ((29, 97), [(43, 83)])]

但当然它并没有产生我想要的结果。 有没有办法以更加pythonic的方式(比下面)完成这个?


我知道可以通过另一次迭代完成:

neighbourhood = [[y[0] for y in all_neighbours if y[1] == x] for x in centroids]

for neigh,cent in zip(neighbourhood, centroids):
    neigh.append(cent)

1 个答案:

答案 0 :(得分:1)

import operator, itertools
all_neighbours = [((28, 145), (25, 125)), ((65, 140), (44, 105)),
                  ((50, 130), (25, 125)), ((38, 115), (44, 105)),
                  ((55, 118), (44, 105)), ((50, 90),  (44, 105)),
                  ((63, 88 ), (44, 105)), ((43, 83 ), (29, 97 )),
                  ((50, 60),  (55, 63 )), ((50, 30 ), (55, 20 ))]

按质心对列表进行排序 -

centroid = operator.itemgetter(1)
point = operator.itemgetter(0)

all_neighbours.sort(key = centroid)

使用itertools.groupby生成群组

for centre, points in itertools.groupby(all_neighbours, centroid):
    print tuple([centre] + map(point, points))

neighbourhoods = [tuple([centre] + map(point, points)) for centre, points
                  in itertools.groupby(all_neighbours, centroid)]