Python: 找到两个列表中最常见的元素
我有两个列表,一个存放点的x坐标,另一个存放y坐标,每个对应的元素代表一个点。
举个例子,X_List = [1, 3, 1, 4],Y_List = [6, 7, 6, 1],那么这些点就是(1,6)、(3,7)、(1,6)和(4,1)。所以,出现次数最多的点是(1,6)。
这是我的代码:
Points=[]
for x,y in zip(X_List, Y_List):
Points.append([x,y])
MostCommonPoint = max(set(Points), key=Points.count)
但是,这样做不行,因为列表里的点是不可哈希的类型。
3 个回答
1
@jan-vlcinsky 说得很对。还有一种更简单的方法,看起来也能正常工作。不过我还没有比较过它们的性能。
在线运行示例: https://repl.it/C9jQ/0
代码片段: https://gist.github.com/ablaze8/845107aa8045507057c1e71b81f228f4
import itertools
a = [7, 3]
b = [3, 1, 2]
c = [4, 3, 5]
def allEqual(t):
same = True
if len(t) == 1:
return True
if len(t) == 0:
return False
for i in range(1, len(t)):
if t[i] != t[i - 1]:
same = False
i = len(t) - 1
else:
same = same and True
return same
combo = list(itertools.product(a, b, c))
# print list(itertools.permutations(a,2))
# print combo
# combo = [x for x in combo if x[0]==x[1]==x[2]]
# print combo
combo = [x for x in combo if allEqual(x)]
print combo
3
使用计数器:
>>> from collections import Counter
这非常简单:
>>> Counter(zip(x_lst, y_lst)).most_common(1)[0][0]
(1, 6)
一步一步来
构建点的列表:
>>> x_lst = [1, 3, 1, 4]
>>> y_lst = [6, 7, 6, 1]
>>> pnts = zip(x_lst, y_lst)
>>> pnts
[(1, 6), (3, 7), (1, 6), (4, 1)]
创建一个 counter
,它可以计算所有的项目:
>>> counter = Counter(pnts)
>>> counter
Counter({(1, 6): 2, (3, 7): 1, (4, 1): 1})
获取最常见的(一个)项目的列表:
>>> counter.most_common(1)
[((1, 6), 2)]
获取该项目本身:
>>> counter.most_common(1)[0][0]
(1, 6)
4
首先,zip
这个函数会返回一个包含元组的列表(在Python 3中是元组的迭代器)。这意味着你可以直接用zip(X_List, Y_List)
来替代Points
(在Python 3中可以用list(zip(X_List, Y_List))
),这样你的代码也能正常运行。不过,这样做的效率会比较低,时间复杂度是平方级别。
一种更快的方法是使用collections.Counter
,这是一个专门用来计数的字典子类:
import collections
# Produce a Counter mapping each point to how many times it appears.
counts = collections.Counter(zip(X_List, Y_List))
# Find the point with the highest count.
MostCommonPoint = max(counts, key=counts.get)