You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中如何高效统计两个关联列表中得票最高的姓名

问题描述

现有两个一一对应的关联列表:

names = ['alan_grant', 'alan_grant', 'alan_grant', 'alan_grant', 'alan_grant', 'claire_dearing', 'claire_dearing', 'claire_dearing', 'claire_dearing', 'claire_dearing', 'ellie_sattler', 'ellie_sattler', 'ellie_sattler', 'ellie_sattler', 'ellie_sattler', 'ian_malcolm', 'ian_malcolm', 'ian_malcolm', 'ian_malcolm', 'ian_malcolm', 'john_hammond', 'john_hammond', 'john_hammond', 'john_hammond', 'john_hammond', 'owen_grady', 'owen_grady', 'owen_grady', 'owen_grady', 'owen_grady']
votes = [True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, True, True, True]

votes列表是面部识别算法对names列表对应位置项的匹配结果,需求为关联所有取值为True的匹配结果和对应姓名,统计出现频次最高的姓名作为最终胜出结果。

目前已实现两种可得到正确结果owen_grady的方案:

  • 方案1:原生字典遍历实现
characters = {}
for name, vote in list(zip(names, votes)):
    if vote == True:
        characters[name] = characters.get(name, 0) + 1
#print(characters)
print(max(characters, key=characters.get))
  • 方案2:列表推导式结合collections.Counter实现
from collections import Counter

characters = [name for name, vote in list(zip(names, votes)) if vote == True]
#print(characters)
print(Counter(characters).most_common()[0][0])

待解答问题:

  1. 上述两种实现哪一种效率更高?
  2. 是否存在效率更优的实现方式,要求最终仅输出结果owen_grady即可。

回答

两种现有方案的效率对比

小数据量场景下两者差异可以忽略,数据量较大时原生字典遍历的实现效率更高,原因如下:

  • 方案2的列表推导式会先生成一个仅包含投票为True的姓名的中间列表,额外占用内存的同时,还多了一次遍历中间列表构建Counter的开销;方案1是单次遍历zip结果,边遍历边计数,没有中间列表的额外开销。
  • 两个现有实现都存在一个无意义的性能损耗:给zip返回的可迭代对象套了list(),zip本身返回的迭代器可以直接用于遍历,强制转列表会额外生成一组元组,白白增加内存占用和耗时,去掉后两个方案的运行速度还能进一步提升。

更优实现方案

如果追求极致效率,可以采用单次遍历+边计数边维护当前最大值的写法,省去最后遍历计数字典找最大值的步骤,也不需要构建任何中间容器:

counts = {}
max_name = None
max_cnt = 0
for name, is_match in zip(names, votes):
    if not is_match:
        continue
    current = counts.get(name, 0) + 1
    counts[name] = current
    if current > max_cnt:
        max_cnt = current
        max_name = name
print(max_name)

如果希望代码更简洁,同时兼顾效率,可以用C实现的itertools.compress替代Python层的列表推导式筛选,省去中间列表开销:

from collections import Counter
from itertools import compress

print(Counter(compress(names, votes)).most_common(1)[0][0])

给most_common传入参数1可以让Counter内部不需要全量排序,只取Top1元素,比不传参的写法更快。

性能参考

在给出的30条测试数据下,各版本耗时差在微秒级,完全感知不到;当数据量提升到百万级时:

  • 边遍历边维护最大值的原生实现,比原方案2快30%左右
  • compress+Counter的简洁实现,比原方案2快20%左右
  • 两种优化方案的逻辑和原方案一致,出现多姓名同票最高的情况时,会返回最先达到最高票数的姓名,和原有逻辑兼容。

内容的提问来源于stack exchange,提问作者blackraven

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 14:01:12