Python 数据结构:list / dict / set 对应 JS 的哪里?| 基础篇
【Python
list/dict/set+ JSArray/Map/Set】AI 应用开发数据结构选型实战:从顺序数据、键值索引到去重逻辑落地,彻底搞懂前端转 Python 的最佳写法,避开迁移过程中的顺序、可变性与查找复杂度高频坑!

📑 文章目录
- 一、先给结论:Python 对应 JS 是什么?
- 二、
list:Python 的有序数组,对应 JSArray - 三、
dict:Python 的键值映射,对应 JSMap(优先)/Object - 四、
set:Python 去重集合,对应 JSSet - 五、三者怎么配合:AI 应用开发的“选型范式”
- 六、最后:一套快速判断题(写代码直接套)
- 七、结束语:通俗但实用的目标
- 🔍 系列模块导航
同学们好,我是 Eugene(尤金),一名前端出身、正在持续深耕 AI 应用开发的工程师。
(Eugene 发音 /juːˈdʒiːn/,大家怎么顺口怎么叫就好)
如果你也和曾经的我一样:
会前端、会工程化、项目经验不少,
但一提到大模型、RAG、Agent、向量库、AI 架构,感觉概念很多、路径很乱,不知道该从哪一步开始落地。
那这个系列,就是专门为你准备的。
这不是一套“只讲概念”的内容,而是一条前端工程师可执行的 AI 转型路线:
从 Python 与 FastAPI,到大模型 API、Prompt、RAG、Agent、部署与架构,再到项目实战与面试就业。
我会坚持用大白话 + 工程化视角 + 真实场景来讲,
不堆玄学,不绕术语。
我们的目标很明确:
不只是“看懂 AI”,而是“真正做出可上线、可维护、可扩展的 AI 应用”。
你如果是做前端的(比如 Vue 方向),已经写了很多 JS 代码,但要转去做 AI 应用开发,最常见的“卡点”往往不是模型原理,而是日常写代码的数据结构选型:
- 该用
list还是dict? set在 JS 里怎么对应?- 迁移代码时,顺序/可变性/查找复杂度会不会踩坑?
这篇文章用“像教小白一样”的方式,把 Python 的 list / dict / set 对应到 JS 的等价结构,并结合几个可直接运行的完整示例讲清楚:怎么选、为什么这么选、容易踩在哪。
一、先给结论:Python 对应 JS 是什么?
把你熟悉的 JS 观念先套进来:
| Python | 典型用途 | JS 对应物(推荐优先级) |
|---|---|---|
list |
有序集合、需要重复元素 | Array(最常用) |
dict |
键值映射(key -> value),快速按 key 查找 | Map(推荐)或 Object(也能用,但更容易踩坑) |
set |
去重/成员存在性判断 | Set |
一句话:
list↔Arraydict↔Map(或Object)set↔Set
接下来我们逐个讲,并把“为什么这么选”说透。
二、list:Python 的有序数组,对应 JS Array
2.1 核心特征
list 具备这些特征:
- 有序(你插入的顺序会影响遍历结果)
- 可变(可以
append / pop / 修改下标) - 允许重复元素
JS 的 Array 基本就是同一类东西。
2.2 选择场景:什么时候用 list / Array?
当你需要:
- 按顺序保存数据(例如聊天历史、时间序列、模型输出的片段)
- 允许重复(例如频率统计前的原始数据列表)
- 你常常使用下标访问、切片、遍历
就优先用 list / Array。
2.3 示例:统计词频(先收集,再统计)
Python 版本(用 list 收集词)
# -*- coding: utf-8 -*-
text = "ai ai python vue ai"
words = text.split() # 这里得到的是 list
print("words:", words)
# 统计词频:先用 dict(后面会讲),但 words 用 list 来承载原始序列
freq = {}
for w in words:
freq[w] = freq.get(w, 0) + 1
print("freq:", freq)
JS 版本(用 Array 收集词)
const text = "ai ai python vue ai";
const words = text.split(" "); // Array
console.log("words:", words);
// 统计词频:最终要用 Map/Object(见 dict 对应)
const freq = new Map();
for (const w of words) {
freq.set(w, (freq.get(w) ?? 0) + 1);
}
console.log("freq:", Object.fromEntries(freq));
你会发现:
list/Array很适合做“数据容器”- 具体的“快速按 key 查找”要用
dict/Map
2.4 常见坑(list ↔ Array)
- 别以为“按值查找很快”
list/Array查找某个值是否存在,通常是线性扫描(概念上类似 O(n))。- 如果你需要“成员存在性判断/去重”,应该用
set/Set。
- 如果你需要“成员存在性判断/去重”,应该用
- 下标越界/切片理解差异
- Python 切片
a[1:3]不会报错(会得到空或更短) - JS 也类似,但要注意你用的方法(
slice)和可能的类型变化。
- Python 切片
- 修改时机要明确
比如你在 for 遍历时删除元素,可能导致逻辑错乱。实践上:优先用新数组/明确策略,而不是边遍历边乱删。
三、dict:Python 的键值映射,对应 JS Map(优先)/ Object
3.1 核心特征
dict 最重要的特性是:
- 用 key 快速定位 value
- key 必须是可哈希类型(通常是字符串、数字、元组等)
- 对“按 key 查找/更新”非常高效(思维上是接近常数时间)
JS 里对应的是:
Map:语义最贴近dictObject:也能做 key -> value,但有些边界情况更容易踩坑(尤其是 key 类型、继承链、遍历行为等)
3.2 选择场景:什么时候用 dict / Map?
当你需要:
- “根据某个字段快速取值”
- “把一个维度映射到另一个维度”
- “做索引/缓存/统计表”(AI 应用很常见)
例如 AI 应用里常见:
- 缓存:
cache[key] = embedding - 解析:
json_dict["choices"][0]["message"]["content"] - 统计:每个用户/每个会话的状态表
这时候 dict/Map 就是王道。
3.3 示例:按 id 聚合数据(list + dict 的典型组合)
Python:用 dict 做聚合表
users = [
{"id": 1, "name": "Alice", "score": 10},
{"id": 1, "name": "Alice", "score": 15},
{"id": 2, "name": "Bob", "score": 8},
]
# 聚合:id -> 总分
score_by_id = {}
for u in users:
uid = u["id"]
score_by_id[uid] = score_by_id.get(uid, 0) + u["score"]
print(score_by_id) # {1: 25, 2: 8}
JS:用 Map 做同样的聚合
const users = [
{ id: 1, name: "Alice", score: 10 },
{ id: 1, name: "Alice", score: 15 },
{ id: 2, name: "Bob", score: 8 },
];
const scoreById = new Map();
for (const u of users) {
const uid = u.id;
const prev = scoreById.get(uid) ?? 0;
scoreById.set(uid, prev + u.score);
}
console.log(Object.fromEntries(scoreById)); // { '1': 25, '2': 8 }
3.4 为什么不建议你总用 JS 的 Object?
Object 能用,但它有几个“前端老鸟常见误区”:
Object的 key 会被强制转换为字符串(Map不会)Object有原型链:你如果随便用普通对象做 key,可能遇到意外属性(比如__proto__相关问题)Map的语义更清晰:你就是要做“键值映射表”,用Map更直观、更安全
所以从“可读性”和“少踩坑”的角度:
dict↔Map(推荐)Object适合你确定 key 都是普通字符串,且你非常清楚它的边界
3.5 常见坑(dict ↔ Map/Object)
- 把“存在性”写错了
- Python:
if key in d: ... - JS:
map.has(key)最清晰
不要用奇怪的“值为假就当不存在”,因为 value 可能是0、""等。
- Python:
- 忘了默认值
- Python:
d.get(key, default) - JS:
map.get(key) ?? default
- Python:
- key 的类型一致性
Map支持 key 为不同类型并严格区分(1和"1"是不同的)- 迁移代码时特别容易写错
四、set:Python 去重集合,对应 JS Set
4.1 核心特征
set 具备:
- 自动去重
- 快速判断成员是否存在(思维上接近常数时间)
- 不关心顺序(你不要依赖插入顺序做业务逻辑)
JS 的 Set 就是同类概念。
4.2 选择场景:什么时候用 set / Set?
当你需要:
- 去重(例如去除重复的页面 URL、重复的候选文档)
- 判断某元素是否出现过(例如过滤已处理的任务 id)
- 收集唯一值,再转回
list/Array做后续处理
AI 应用里也非常常见:
- 去重召回文档
- 去重 token(例如某些词表处理)
- 跟踪已请求/已生成过的内容 id(避免重复调用)
4.3 示例:去重并统计唯一用户
Python:用 set 去重
user_ids = [1, 2, 2, 3, 3, 3]
unique_ids = set(user_ids)
print("unique_ids:", unique_ids)
print("count:", len(unique_ids))
JS:用 Set 去重
const userIds = [1, 2, 2, 3, 3, 3];
const uniqueIds = new Set(userIds);
console.log("uniqueIds:", Array.from(uniqueIds));
console.log("count:", uniqueIds.size);
4.4 常见坑(set ↔ Set)
- 不要在业务上依赖顺序
如果你需要“既去重又要顺序”,这时要用额外结构(例如list+set组合策略),不要直接只用set。 - 只能放可哈希元素(Python 的 set)
- Python:list 不能作为
set元素,因为 list 不可哈希 - JS:
Set可以放对象引用,但“内容相等”不是同一回事
迁移时最容易误解:“两个内容相同的对象”在 JS 的Set里不一定会去重,因为引用不同。
- Python:list 不能作为
五、三者怎么配合:AI 应用开发的“选型范式”
你在 AI 应用里经常会遇到这种数据流:
- 模型输出是“列表/序列”(token、候选项、消息历史)
- 需要按某个字段做快速查找(按用户 id、按文档 id、按会话 id)
- 需要去重(同一条候选不重复处理)
因此一个非常实用的组合范式是:
- 用
list/Array:承载“顺序数据” - 用
dict/Map:承载“按 key 查找的数据表” - 用
set/Set:承载“唯一性/去重/已处理集合”
5.1 一个综合例子:从一堆候选里去重并聚合评分
Python
candidates = [
{"doc_id": "d1", "score": 0.2},
{"doc_id": "d2", "score": 0.4},
{"doc_id": "d1", "score": 0.3}, # 重复 doc_id
]
seen = set() # set:去重控制
sum_score = {} # dict:doc_id -> 累计分
count_by_doc = {} # dict:doc_id -> 出现次数
for c in candidates:
doc_id = c["doc_id"]
score = c["score"]
# 这里我们不只是“去重保留第一条”,而是统计累计分
sum_score[doc_id] = sum_score.get(doc_id, 0) + score
count_by_doc[doc_id] = count_by_doc.get(doc_id, 0) + 1
seen.add(doc_id)
print("unique docs:", seen)
print("sum_score:", sum_score)
print("count_by_doc:", count_by_doc)
JS
const candidates = [
{ doc_id: "d1", score: 0.2 },
{ doc_id: "d2", score: 0.4 },
{ doc_id: "d1", score: 0.3 },
];
const seen = new Set(); // Set
const sumScore = new Map(); // Map
const countByDoc = new Map(); // Map
for (const c of candidates) {
const docId = c.doc_id;
const score = c.score;
sumScore.set(docId, (sumScore.get(docId) ?? 0) + score);
countByDoc.set(docId, (countByDoc.get(docId) ?? 0) + 1);
seen.add(docId);
}
console.log("unique docs:", Array.from(seen));
console.log("sum_score:", Object.fromEntries(sumScore));
console.log("count_by_doc:", Object.fromEntries(countByDoc));
这段示例背后的“选型逻辑”很关键:
set:保证我们能拿到唯一 docdict/Map:用 doc_id 做索引,把统计结果存起来list:候选本身自然是序列输入
六、最后:一套快速判断题(写代码直接套)
当你遇到新需求,在你写代码前先问这三句:
-
我需要“顺序/可重复”吗?
是 ->list / Array
否 -> 看下面 -
我需要“按 key 快速取值/更新”吗?
是 ->dict / Map
否 -> 看下面 -
我需要“去重/判断是否出现过”吗?
是 ->set / Set
如果三者都需要,就按组合范式:
- 序列用
list/Array - 索引用
dict/Map - 唯一性用
set/Set
七、结束语:通俗但实用的目标
从“前端老鸟”转向“AI 应用开发工程师”,不需要一上来就啃玄学原理。
真正能让你写得快、写得对、写得不返工的,是这些日常工程能力:数据结构选型 + 避坑意识。
这篇文章讲的 list / dict / set,就是在 AI 应用里绕不开的基础工具。后面你继续把它们用在:
- prompt 拼装(消息历史:
list+ 按角色索引:dict) - 结果去重(候选文档:
set) - 缓存/追踪(调用状态:
dict/Map)
就会发现“AI 开发”其实也和普通工程一样:本质是把数据组织好,再把流程跑起来。
🔍 系列模块导航
📝 AI应用开发工程师基础篇
一、《AI大模型应用开发怎么入门?认知、选型与避坑指南| 基础篇》
二、《AI 开发工程师到底是什么?| 基础篇》
三、《为什么 AI 应用开发首选 Python?|基础篇》
四、《Python + venv + VSCode:前端工程师 AI 转型入门|基础篇》
五、《Python 基础语法:7 天快速上手|基础篇》
六、《Python 数据结构:list 、 dict 、 set 对应 JS 的哪里?| 基础篇》
七、《Python 函数与模块化:前端工程化思维完全通用| 基础篇》
八、《Python 异步 async/await:为什么 AI 框架大量使用?| 基础篇》
👉 跟着系列慢慢学,把技术功底扎扎实实地打牢~
📚 系列总览
- AI 应用开发从 0 到 1:前端转 AI 完整体系(持续更新中)
系列完结后会整理成一篇完整导航文并附上直达链接,方便大家按顺序、体系化学习。
全套内容持续更新中,敬请期待~
AI 时代,真正稀缺的不是会调用一个模型接口的人,
而是能把业务、工程、架构、模型能力连接起来,做成完整产品的工程师。
前端转 AI,不是推倒重来,而是把你原有的工程化能力升级到新的技术栈里。
你过去积累的组件化、性能优化、协作规范、系统思维,都会在 AI 项目中继续产生价值。
后续我会持续更新这个系列:
覆盖基础认知、RAG、Agent、函数调用、开源模型部署、企业级架构、项目实战与面试求职,
帮你一步步从「会写页面」走向「能交付 AI 应用」。
如果这篇对你有帮助,欢迎 点赞 + 收藏 + 关注。
把这套系列当作你的 AI 转型路线图,跟着节奏持续推进,你会看到非常明显的成长。
我是 Eugene,你的电子学友,我们下篇干货见~
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)