讲师中心 微信公众号
AI工具推荐 视频效率加速

Python中基于字典映射对列表元素进行高效计数

风枫小哥_5599

风枫小哥_5599

发布时间:2025-12-03 13:34:02

|

1035人浏览过

|

来源于php中文网

原创

python中基于字典映射对列表元素进行高效计数

本教程详细探讨了如何在Python中根据字典键值列表高效统计主列表中特定元素的出现次数。针对常见但低效的嵌套循环方案,文章提出了一种通过预处理主列表来优化性能的方法,将时间复杂度从O(N³)显著降低至O(N),并提供了详细的Python代码实现、性能分析及最佳实践建议。

问题描述

在Python编程中,我们经常会遇到需要根据特定映射关系统计元素出现次数的场景。具体来说,假设我们有一个字典 my_dict,其键是字符串,值是包含字符串元素的列表。同时,我们还有一个主列表 my_list。我们的目标是创建一个新的字典 new_dict,其中 new_dict 的键与 my_dict 的键相同,而 new_dict 的值则是 my_dict 中对应键的值列表里所有元素在 my_list 中出现的总次数。

例如,给定以下数据:

my_dict = {'A': ['A', 'B'], 'B': ['C', 'D'], 'C': ['E', 'F']}
my_list = ['A', 'D', 'A', 'C', 'F', 'F']
new_dict = {}

我们期望的输出是:

立即学习“Python免费学习笔记(深入)”;

{'A': 2, 'B': 2, 'C': 2}

解释:

  • 对于键 'A',my_dict 的值为 ['A', 'B']。在 my_list 中,'A' 出现了 2 次,'B' 出现了 0 次。所以 'A' 的总计数为 2。
  • 对于键 'B',my_dict 的值为 ['C', 'D']。在 my_list 中,'C' 出现了 1 次,'D' 出现了 1 次。所以 'B' 的总计数为 1 + 1 = 2。
  • 对于键 'C',my_dict 的值为 ['E', 'F']。在 my_list 中,'E' 出现了 0 次,'F' 出现了 2 次。所以 'C' 的总计数为 2。

低效的初始方法及其性能瓶颈

初学者可能会尝试使用多层嵌套循环来解决这个问题。一种常见的思路是遍历 my_dict 的每个键值对,然后对于每个值列表中的元素,再遍历 my_list 来计数。

伪代码可能如下:

new_dict = {}
for key, values_list in my_dict.items():
    current_key_count = 0
    for item_to_count in values_list:
        for element_in_main_list in my_list:
            if item_to_count == element_in_main_list:
                current_key_count += 1
    new_dict[key] = current_key_count

或者,如果使用 list.count() 方法,虽然代码看起来简洁,但内部逻辑依然是遍历:

new_dict = {}
for key, values_list in my_dict.items():
    current_key_count = 0
    for item_to_count in values_list:
        current_key_count += my_list.count(item_to_count) # my_list.count() 内部会遍历 my_list
    new_dict[key] = current_key_count

这种方法的性能瓶颈在于其时间复杂度。让我们分析一下:

  1. 外层循环: 遍历 my_dict 的键值对,假设有 K 个键。
  2. 中层循环: 对于 my_dict 的每个键,遍历其值列表中的元素,假设平均每个值列表有 L 个元素。
  3. 内层操作:
    • 如果直接使用 for element_in_main_list in my_list 进行比较,这相当于遍历 my_list,假设 my_list 有 N 个元素。
    • 如果使用 my_list.count(item),Python 内部也会遍历 my_list 来计数,其时间复杂度为 O(N)。

因此,总的时间复杂度大致为 O(K * L * N)。在最坏情况下,如果 K、L、N 都很大,这将导致 O(N^3) 级别的性能,这是非常低效的。例如,在示例输入中,K=3,N=6,平均 L=2,迭代次数约为 3 * 2 * 6 = 36 次。虽然对于小数据集尚可接受,但对于大规模数据,这种方法将变得不可用。

macOS UI 自动化技能包 —— 用 Python 控制你的 Mac
macOS UI 自动化技能包 —— 用 Python 控制你的 Mac

让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限

下载

高效解决方案:预处理与字典查找

为了提高效率,我们可以采用一种策略:首先对 my_list 进行预处理,计算其中每个元素的出现次数,并将其存储在一个字典中。由于字典的查找操作通常是 O(1)(常数时间),这可以大大减少重复的遍历操作。

这种方法的算法步骤如下:

  1. 预处理 my_list: 遍历 my_list,创建一个名为 counts 的字典,存储 my_list 中每个元素及其出现次数。这一步的时间复杂度为 O(N_list),其中 N_list 是 my_list 的长度。
  2. 计算 new_dict: 遍历 my_dict 的每个键值对。对于每个键,初始化一个计数器。然后,遍历该键对应的值列表中的每个元素。对于值列表中的每个元素,到 counts 字典中查找其预先计算好的出现次数,并累加到当前键的计数器中。最后,将累加结果存入 new_dict。

详细代码实现(Vanilla Python)

以下是使用纯Python实现上述高效方法的函数:

def count_nested_values(my_dict: dict, my_list: list) -> dict:
    """
    根据字典映射关系,高效统计主列表中元素的出现次数。

    参数:
        my_dict (dict): 字典,键为字符串,值为包含字符串元素的列表。
        my_list (list): 主列表,包含字符串元素。

    返回:
        dict: 新字典,键与my_dict相同,值为对应元素在my_list中的总出现次数。
    """
    # 步骤1: 预处理 my_list,计算每个元素的出现次数
    # 使用字典存储,实现 O(1) 的查找性能
    counts = {}
    for list_val in my_list:
        counts[list_val] = counts.get(list_val, 0) + 1 # 使用 .get() 避免 KeyError

    # 步骤2: 根据 my_dict 的映射关系,累加预处理后的计数
    new_dict = {}
    for k, dict_val_list in my_dict.items():
        current_key_total_count = 0
        # 遍历 my_dict 中当前键对应的值列表
        for item_to_count in dict_val_list:
            # 从预处理的 counts 字典中获取该元素的计数
            # 如果元素不在 counts 中 (即不在 my_list 中出现),则计为 0
            current_key_total_count += counts.get(item_to_count, 0)
        new_dict[k] = current_key_total_count

    return new_dict

# 示例用法
my_dict_example = {'A': ['A', 'B'], 'B': ['C', 'D'], 'C': ['E', 'F']}
my_list_example = ['A', 'D', 'A', 'C', 'F', 'F']

result_dict = count_nested_values(my_dict_example, my_list_example)
print(result_dict)
# 预期输出: {'A': 2, 'B': 2, 'C': 2}

代码解析:

  1. counts = {} 初始化: 创建一个空字典 counts,用于存储 my_list 中每个元素的频率。
  2. 第一个 for 循环:
    • for list_val in my_list::遍历 my_list 中的每一个元素。
    • counts[list_val] = counts.get(list_val, 0) + 1:如果 list_val 已经在 counts 中,则将其计数加 1;否则,将其初始化为 1。dict.get(key, default_value) 方法是一个优雅的处理方式,避免了 KeyError。
  3. new_dict = {} 初始化: 创建一个空字典 new_dict,用于存储最终结果。
  4. 第二个 for 循环:
    • for k, dict_val_list in my_dict.items()::遍历 my_dict 中的每一个键值对。
    • current_key_total_count = 0:为当前 my_dict 的键初始化一个总计数器。
    • 内层 for 循环:
      • for item_to_count in dict_val_list::遍历当前 my_dict 键对应的列表 dict_val_list 中的每一个元素。
      • current_key_total_count += counts.get(item_to_count, 0):从 counts 字典中查找 item_to_count 的出现次数。如果 item_to_count 不在 my_list 中(因此不在 counts 字典中),get() 方法会返回默认值 0,确保不会影响总计数。
    • new_dict[k] = current_key_total_count:将累加的总计数赋值给 new_dict 中对应的键。

性能分析

现在我们来分析一下优化后的解决方案的时间复杂度:

  1. 预处理 my_list (counts 字典的构建):

    • 遍历 my_list 的所有元素。
    • 对于每个元素,执行字典的查找和更新操作。由于字典的平均查找和插入操作是 O(1)(常数时间),这一步的总时间复杂度为 O(N_list),其中 N_list 是 my_list 的长度。
  2. 构建 new_dict:

    • 遍历 my_dict 的所有键值对。假设 my_dict 有 N_keys 个键。
    • 对于 my_dict 的每个键,我们遍历其对应的值列表。假设所有值列表中的元素总数为 N_nested_values(即 sum(len(v) for v in my_dict.values()))。
    • 在内层循环中,我们执行字典的查找操作 (counts.get()),这仍然是 O(1)。

因此,第二步的总时间复杂度为 O(N_keys + N_nested_values)。

综合来看,整个算法的总时间复杂度为 O(N_list + N_keys + N_nested_values)。 我们可以将其简化为 O(N),其中 N 是所有相关输入数据(my_list 的长度、my_dict 的键数量以及所有嵌套列表的元素总数)的总规模。

与之前 O(N^3) 的低效方法相比,O(N) 算法的性能提升是巨大的,尤其是在处理大规模数据集时。例如,如果 my_list 有 1000 个元素,my_dict 有 100 个键,每个值列表平均有 10 个元素:

  • 低效方法:100 * 10 * 1000 = 1,000,000 次操作。
  • 高效方法:1000 + 100 + (100 * 10) = 1000 + 100 + 1000 = 2100 次操作。 性能差异显而易见。

注意事项与最佳实践

  1. 选择合适的数据结构: 这个案例的核心在于利用字典的 O(1) 平均查找时间来优化性能。当需要频繁查找元素是否存在或获取其属性时,字典(或集合)通常是比列表更好的选择。
  2. 预处理的价值: 当某个计算结果会被多次复用时,考虑进行一次性预处理并存储结果,可以避免重复计算,从而显著提高整体效率。
  3. 了解时间复杂度: 理解不同操作和算法的时间复杂度(如 O(1)、O(N)、O(N^2)、O(log N) 等)是编写高效代码的关键。这有助于在设计解决方案时预判其在大规模数据下的表现。
  4. collections.Counter 模块: Python标准库 collections 中的 Counter 类可以更简洁地完成 my_list 的预处理步骤。例如,counts = Counter(my_list) 即可实现与第一个 for 循环相同的功能。如果允许使用库,这会是更Pythonic且可能更优化的选择。本教程提供的纯Python实现,旨在展示其底层原理。

总结

本教程通过一个具体的列表元素计数问题,演示了如何从一个低效的 O(N^3) 解决方案,通过引入预处理和利用字典的 O(1) 查找特性,将其优化为高效的 O(N) 解决方案。理解并应用这些优化原则,对于编写高性能的Python代码至关重要。在实际开发中,始终优先考虑数据结构的选择和算法设计,以确保程序在面对不同规模数据时都能保持良好的性能。

热门AI工具

更多
PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

超级麦吉

一款通过数字员工协作完成调研、数据分析与文档制作的AI办公平台。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

小橡皮AI

一款AI工具,主要用于小橡皮一键去AI味,将机器味重的内容改得更有活人感,防止因为 AI 内容被平台打上 AI 标签,以及限流,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

相关专题

更多
counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3408

2023.11.20

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1798

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2844

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6184

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

5969

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

7574

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

11294

2024.04.29

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

5819

2025.07.29

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

20

2026.10.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Uvicorn官方安装与入门手册
Uvicorn官方安装与入门手册

共0课时 | 0人学习

Python uv官方项目管理指南
Python uv官方项目管理指南

共0课时 | 0人学习

Python uv官方安装与入门文档
Python uv官方安装与入门文档

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn