ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

列表去重全攻略:从5种基础写法到7个实战细节

列表去重全攻略:从5种基础写法到7个实战细节 “5-7列表去重”这个题目乍一看像是某个培训课程里的章节编号但我更多把它理解成一次从入门到进阶的梳理——从最基础的5种去重写法到实战中必须掌握的7个性能与场景细节。列表去重这个操作几乎是所有写代码的人都绕不开的日常Python里有列表listJavaScript里有数组ArraySQL里有查询结果集连Excel下拉列表的去重都能算半个。但就是这么一个看似“一个set就搞定”的小功能真到了生产环境、笔试现场、数据处理任务里坑多得超出想象。这篇文章我就把列表去重这件事从原理到实操、从Python到JavaScript再到SQL完整掰开揉碎讲一遍适合刚入门想打牢基础的新手也适合写了大半年代码但没系统整理过去重方案的进阶读者。1. 去重这个需求到底难在哪先看清问题的本质1.1 你以为的去重和实际遇到的去重不是一回事先说个我自己的经历。早年我在一个数据清洗的脚本里写过去重当时数据量不大两三千条我直接用了set()代码跑得飞快心里还挺美。后来项目上了量几十万行用户行为日志要按设备ID去重set一上去内存直接爆了服务器差点被搞挂。那次之后我才意识到去重这件事表面上看是“把重复的删掉”但实际拆开来看至少包含四个维度去重的对象是什么类型字符串、数字、字典、对象、要不要保留原始顺序、数据量有多大内存能不能扛住、去重后还要不要保留最后一条而不是第一条。如果只是简单值去重比如列表里全是整数或字符串那确实没什么好讲的set一下完事。但面试和实战里真正考的是另外三种情况对象字典去重、大数据量去重、以及去重后排序规则的定义。这几类问题光靠set是解决不了的你得自己定义“唯一性”的标准。举个例子用户表里有两条记录姓名相同但ID不同到底算不算重复这取决于业务需求而不只是编程技巧。1.2 为什么“唯一性标准”是去重的灵魂很多新手写去重代码容易犯一个毛病用肉眼觉得“这两条好像一样”然后在代码里就去掉了。但程序不会看“好像”它只会按照你给定的规则去判断。所以写去重之前先回答三个问题哪些字段相同就判定为重复比如手机号、身份证号、还是姓名地址的组合如果重复了保留哪一条第一条、最后一条、还是某个字段值最大的那条去重后的顺序有什么要求吗保持原顺序、按某个字段排序我把这三点称为“去重三问”。任何一次去重操作只要把这三问答清楚了代码怎么写其实已经定了一半。剩下的就是选择合适的数据结构和算法。我见过不少线上事故就是因为没想清楚第二问——保留哪条。比如在消息推送场景里同一个用户短期内收到了多条重复通知系统要做去重如果只保留最早的那条用户就可能错过最新的消息内容如果保留最后一条就要求遍历方向得反过来。这种细节比set还是dict哪个快更重要。2. 基础玩法盘点5种最常见列表去重写法及原理2.1 用集合set去重最快但别忽略顺序问题先聊最经典的set去重代码短、性能好但有个天生缺陷不保证顺序。Python里set是基于哈希表实现的存储时不关心你把数据放进去的顺序。所以在Python 3.7之前set去重后的列表顺序完全是随机的3.7之后虽然dict有序了但set本身依然无序。JavaScript这边的Set对象稍微好一点它按照插入顺序迭代所以在JS里[...new Set(arr)]能保持顺序。同样是set两种语言行为还不一样这就能看出跨语言经验的重要性。# Python 基础set去重 data [3, 1, 2, 3, 1, 4, 5, 2] unique_data list(set(data)) print(unique_data) # 结果不保证顺序可能是 [1, 2, 3, 4, 5] 的任意排列如果你想用set去重又必须保持顺序那就得配合列表推导式或者循环来搭一个“seen集合”# 保持顺序的set辅助去重 seen set() result [] for item in data: if item not in seen: seen.add(item) result.append(item) print(result) # [3, 1, 2, 4, 5]顺序保留这块值得展开说。set底层是无序哈希表它的查找是O(1)的所以这个“seen集合遍历”的写法时间上依然很快空间上多了一个set的开销。这也是笔试里最常考的解法之一面试官看到你能答出“set能达到O(1)查找再配合遍历保持顺序”就已经和普通选手拉开差距了。2.2 字典dict.fromkeys去重兼顾顺序与稳定性的老古董在Python里还有一个老牌写法dict.fromkeys()。它的逻辑是把列表元素作为字典的键利用字典键唯一的特性去重。在Python 3.7里字典保持插入顺序所以这个方法天然稳定。data [apple, banana, apple, orange, banana] result list(dict.fromkeys(data)) print(result) # [apple, banana, orange]为什么不用set而用dict.fromkeys因为旧版Python里set无序而dict虽然也是哈希表但在3.7之后却记录插入顺序实质上是链表哈希索引的实现。所以在“去重保序”这个组合需求下dict.fromkeys是一个不用写循环的优雅方案。对于JavaScript开发者来说这个思路对应的是手动维护一个Map或Set对象因为JS没有直接的fromKeys数组方法但Map的插入顺序特性是一样的。2.3 遍历新列表手工去重理解力第一性能第二当你面对的是一个复杂对象数组Python里是字典列表JS里是对象数组时set和dict.fromkeys就不太好使了因为列表里的每个字典本身是不能哈希的unhashable。这时候最朴素也最灵活的办法就是遍历自己维护一个“唯一性标记”。我见过很多教程说遍历效率低但其实在数据量不大的时候遍历反而是最直观、最好维护的方案。比如data [ {name: 张三, age: 20}, {name: 李四, age: 22}, {name: 张三, age: 30}, ] seen set() result [] for item in data: key item[name] # 按姓名去重 if key not in seen: seen.add(key) result.append(item) print(result) # 输出第一条张三而非30岁的张三这类写法终极优势在于你可以通过把key定义成任何组合比如(item[name], item[age])来满足业务上的“唯一性标准”。代价是代码多几行但可读性极高别人一看就懂你按什么规则去重。团队协作时这种可读性比省几毫秒宝贵得多。2.4 排序相邻比对去重不依赖哈希结构的方法还有一种掌握频率较低但值得会的思路先排序再相邻比对遇到相同的就跳过。这在C语言这类没有内置Set结构的场景更常见但在Python、JavaScript里也能用。它的原理非常简单排序后重复元素会靠在一起那你只需要声明一个空结果表逐一遍历如果当前元素和上一个不同就加入结果。data [5, 3, 1, 3, 5, 2, 1] data.sort() # [1, 1, 2, 3, 3, 5, 5] result [] for i in range(len(data)): if i 0 or data[i] ! data[i - 1]: result.append(data[i]) print(result) # [1, 2, 3, 5]这个方案的时间复杂度是O(n log n)主要花在排序上。数据量很大但内存受限比如嵌入式环境时它可以节省额外set的空间开销因为除了排序占用的存储你甚至不需要保存“已见过的元素”。代价是原始顺序丢失。如果你能灵活回答出这种方案和set方案的取舍在技术面试里会显得底层功底很扎实。2.5 一行式的filterindex高级玩法炫技但需要小心在JavaScript里有一种很时髦的金句写法const arr [1, 2, 1, 3, 2, 4]; const unique arr.filter((value, index) arr.indexOf(value) index); console.log(unique); // [1, 2, 3, 4]这个逻辑其实就是“如果当前元素第一次出现的位置就是当前位置说明它此前没出现过”。代码看起来极度简洁面试时写出来确实加分但它的性能是O(n²)的arr.indexOf要遍历整个数组才能知道value第一次出现在哪所以体内嵌套了一层查找。数据量一旦超过几千体感就会很明显。我自己的经验是代码题、教学演示可以用但生产环境尽量别用这个写法。真正在生产环境里推荐的JavaScript去重写法是const unique [...new Set(arr)];或者用Map处理带对象属性的去重const objArr [ { id: 1, name: a }, { id: 2, name: b }, { id: 1, name: c }, ]; const seen new Map(); const uniqueObj objArr.filter(item { if (!seen.has(item.id)) { seen.set(item.id, item); return true; } return false; }); console.log(uniqueObj); // [{ id: 1, name: a }, { id: 2, name: b }]3. 进阶硬核场景7个你必须掌握的实战细节3.1 对象数组按多个字段去重把Key变成元组热搜词里“对象数组去重”反复出现说明这是大家在实际中最大的痛点之一。对象数组去重的核心就是定义一个“合成key”。在Python中可以用元组在JavaScript中可以用JSON.stringify把多个字段拼成字符串或者用反引号模板拼接。举个例子电商订单按“用户ID 商品ID”去重orders [ {user_id: 1, product_id: 101, price: 9.9}, {user_id: 1, product_id: 101, price: 8.8}, {user_id: 2, product_id: 101, price: 9.9}, ] seen set() result [] for order in orders: key (order[user_id], order[product_id]) if key not in seen: seen.add(key) result.append(order) print(result) # 保留两条重复订单中的8.8被去掉这里有个值得说的点在这个数组里去重后到底保留9.9还是8.8按照上面的写法保留的是9.9因为它是第一条出现的。但我见过很多业务场景要求保留“最新的一条”也就是后面出现的8.8假设后出现的才是改价后的新数据。如果是那样遍历方向就得反过来从列表末尾往前遍历或者直接用新数据覆盖seen对应的旧记录。这个细节非常容易忽略但直接影响业务正确性。我建议每个开发者在写去重前养成本能先确认保留哪一条。3.2 大数据量去重的内存优化用布隆过滤器降低内存占用这是“7个细节”里含金量最高的一个。当列表量达到千万级甚至亿级你不可能用一个set把全部元素展开。比如一百亿个用户ID每个ID算16字节set还会附带哈希表的额外存储开销内存可能是原始数据的3~5倍。实际扛不住。业内常用方案是分治加哈希先把数据按照哈希值分到多个文件每个文件内单独去重或者用布隆过滤器Bloom Filter这种概率型数据结构先过滤掉绝大多数重复项少量误判再回源数据库复核。我没法在这里给你写出工业级完整实现但可以给一个通用思路如果数据在数据库里用SQL的DISTINCT或GROUP BY交给数据库引擎处理别取到内存里再排。如果数据是日志文件流式读取边读边写设置一个大小可控的seen集合满了就把已去重结果落盘再清空set。如果业务允许极低比例的误判用布隆过滤器做第一层过滤剩余候选再精确去重。网上有个很形象的比喻用set去重就像把所有东西搬进屋再分类用布隆过滤器去重就像是先在大门口问一句“这东西来过没有”只有似是而非的人才进屋细查。这套方法论在处理亿级设备ID、日志清洗时非常管用。3.3 SQL层面的去重查询DISTINCT和GROUP BY怎么选热搜词里“sql语句去重”、“sql语句去重查询”出现了好几次我单独拿一节说。SQL去重最常见的是两种写法-- 方式一DISTINCT SELECT DISTINCT user_id FROM orders; -- 方式二GROUP BY SELECT user_id FROM orders GROUP BY user_id;很多人以为这两种写法完全等价其实差别很大。DISTINCT的语义就是把重复行去掉写法最简单GROUP BY本质是分组聚合它的能力远不止去重你可以在后面接COUNT、SUM、MAX等聚合函数。举个例子如果你想看每个用户下了多少单就只能用GROUP BY。另外如果你只想去重但还想带出其他字段DISTINCT会把所有选中的字段组合当成一个整体来去重而GROUP BY搭配任意值函数的写法各不相同这在不同的数据库MySQL、SQL Server、PostgreSQL里还有细微差别很容易踩坑。有一个更刁钻的需求按某个字段去重但返回整行记录。这种事情SQL标准里没有一条“去重保留一条”的语法直接搞定常见的写法是窗口函数ROW_NUMBER()-- 按user_id去重每个user_id保留最新一条订单 SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY create_time DESC) AS rn FROM orders ) t WHERE t.rn 1;这套写法在SQL Server和PostgreSQL里直接支持MySQL 8.0也支持窗口函数了但如果你还在用MySQL 5.7就得换成“自连接取最大ID”之类的经典方案SELECT o.* FROM orders o JOIN ( SELECT user_id, MAX(id) AS max_id FROM orders GROUP BY user_id ) t ON o.id t.max_id;这里顺带回应热搜词里出现的“mssql 去重 多表查询”。多表查询去重时一定要先想清楚重复是因为表本身有重复数据还是因为JOIN造成的笛卡尔积膨胀如果是JOIN造成的去重是治标不治本正确的做法是先按维度字段把子查询缩小范围再JOIN或者用EXISTS替代JOIN。3.4 保持顺序与去重的优先级问题我觉得很值得强调的一个点很多人写去重时没意识到“去重”和“排序”其实是两件独立的事。“去重”负责的是剔除重复项“排序”负责的是按规则调整顺序。但这两件事经常被混在一起。比如一个运营后台要展示“最近活跃用户”要求去掉重复用户且按最近活跃时间排序。有的新手会把去重后的结果再排序结果发现保留哪条取决于去重时机顺序就乱了。正确做法是先按业务规则排好序确保“要保留的那条”出现在合适的位置然后再去重。比如你想保留每个用户最近一条登录记录那应该先按登录时间倒序排列然后用seen集合去重。这样保留下来的天然就是最近一条。这个顺序问题我在实际项目里至少踩过三次每次都修了半天最后发现是把先排序还是先去重的因果关系搞反了。3.5 列表切片与去重组合使用的妙处方向了顺便提一下热搜里的“列表切片”。切片常配合去重来做“分段处理”比如一个大列表没办法一次性加载到内存就可以分片data list(range(1000000)) chunk_size 100000 seen set() result [] for i in range(0, len(data), chunk_size): chunk data[i:i chunk_size] for item in chunk: if item not in seen: seen.add(item) result.append(item)或者当你只需要处理列表的一部分时先切片再去重比全量去重高效得多top_100 data[:100] unique_top_100 list(dict.fromkeys(top_100))Python的切片返回的是新列表会复制一份数据所以切片的开销也不是零。但好处是很灵活。JavaScript对应的方法是slice()或者splice()后者会修改原数组慎用。这个组合技巧在“分页去重”或“抽样去重”场景很实用。3.6 数据清洗中的“脏数据”去重空值与空白字符真正的数据清洗去重前往往还要加一道“规整化”。你在热搜里也能看到“清洗---sql语句去重”的说法可见清洗和去重是天然绑定的。常见的脏数据包括同一个字符串后面带了一个空格比如张三 和张三被判定为不同。全角半角数字混搭如全角和100。None、NaN、空字符串这些特殊值它们是否算重复排查时最稳的命令是把数据的repr形式打印出来或者用正则对关键字段做strip和replace。Python里item.strip()。JavaScript里item.trim()。然后再去重。如果直接对脏数据去重结果列表里依然会有“看起来重复但程序认为不重复”的条目。这才是数据清洗里最隐蔽的坑。3.7 去重后的统计与可视化别只盯着删重复去重不只是“删数据”在数据分析中它往往是统计的准备工作。比如统计独立访客数去重后的用户数、独立设备数。这个场景里你去重后还要对结果继续做聚合、排序、分组。我常见的套路是先把去重结果存成临时表或者变量再基于这个结果继续查。比如WITH unique_users AS ( SELECT DISTINCT user_id FROM visits ) SELECT COUNT(*) FROM unique_users;在Python里同样去重后的result列表可以再传给Pandas的DataFrame做后续分析。记住去重不会是你任务的终点它只是让后续的数据口径更准确。4. 跨语言视角同样的问题不同语言的“最优解”差异很大4.1 Python与JavaScript去重写法对比很多时候大家会纠结学Python还是JavaScript其实对照着看同一算法在不同语言的表达反而理解最快。我先列一张小表语言简单类型去重对象数组按字段去重保序方式Pythonlist(set(data))遍历seen集合key用元组dict.fromkeys()JavaScript[...new Set(arr)]filterMapMap天然保序SQLSELECT DISTINCTGROUP BY ROW_NUMBERORDER BY你看语言是外衣核心思想都绕不开“哈希表、排序、遍历”。写Python的人觉得set爽写JavaScript的人觉得Set也爽但当你处理对象数组时两边的写法都回归到了“自定义一个唯一key”。所以我一直建议初学者别只盯着某个语言死记硬背API把“唯一性标准”想透什么语言都一样。4.2 影刀RPA列表去重里常见的小剧场热搜词里有一条“影刀rpa如何将列表中的[]去掉”这个场景很生活。很多人用影刀抓取网页内容抓到的列表元素里带着中括号或者多余的空格比如[item1, item2]这样。其实那不是列表本身的格式问题而是你把列表转成字符串展示了。真正的处理办法是遍历列表对每个元素strip清洗然后用列表推导式过滤掉空字符串。# 伪代码示意 clean_list [str(item).replace([, ).replace(], ).strip() for item in raw_list]其实和去重无关但属于“对列表进行规整化处理”的常见需求。如果你在影刀里需要去重直接用影刀提供的“列表去重”指令也行或者自己写循环seen集合。影刀的Python环境支持大部分Python语法所以上面的代码基本能平移。4.3 Excel下拉列表的“去重”到底在去什么热搜词“excel设置为下拉列表”和“怎么把下拉列表同步到整列”也很有意思。Excel里创建下拉列表时数据源如果包含重复项下拉选项里会重复显示很丑。一般操作是先对源数据做一次“删除重复值”Excel数据选项卡里有现成功能或者用公式提取唯一值。这个场景里的“去重”和编程里的list去重逻辑完全一致但处理工具不同。你要是Excel老手也可以直接用“数据透视表”拉一列所有唯一值然后把这列作为下拉数据源。你看去重思想到处都在。5. 常见问题与排查技巧实录5.1 为什么用set去重后结果顺序每次都不一样这是初学者问得最多的问题。原因我在前面已经提过set的存储顺序由哈希表决定并不依赖插入顺序。Python里不同版本甚至同一版本不同运行环境下哈希种子hash seed可能不同Python出于安全考虑给字符串哈希引入了随机盐值所以每次运行顺序可能不同。解决方案也很简单去重要保序就别直接list(set(data))用dict.fromkeys或循环seen。如果你用到JavaScript的Set倒是不用担心因为Set的遍历顺序就是插入顺序。这算两种语言一个小而关键的差异。5.2 为什么去重后还是能看到“重复”数据一般三种可能你把浮点数里的精度问题忽略了。比如1.0和1.00在程序里通常相等但0.10.2和0.3则不相等浮点数精度问题。数据是先转字符串再落地的导致1和01被当成不同元素。数据库中的CHAR类型自动补空格导致abc和abc 看似相同实际不同。排查方式先打印每个元素的repr肉眼验证。然后尝试归一化数字统一转成decimal字符串统一strip日期统一格式。只有源数据规整了去重才有意义。5.3 内存不足set存不下几千万条数据怎么办这个问题在第二个大章节里提了布隆过滤器这里再补充一个粗粒度但非常实用的方案分而治之。把大列表拆成若干条小文件按某个hash值取模分桶内存里维护的seen集合只负责处理当前桶。每个桶去重完结果合并。因为同一个重复项目的哈希值一定落在同一个桶里所以不会漏掉重复。这个桶的合并是安全的。你甚至可以先用shell命令对文件按第一个字段排序再用相邻比对去重本质上就是第2章里的“排序相邻比对”方案的分布式版本。5.4 对象数组去重时提示unhashable type: dictPython新手常见报错list(set(data_dict_list)) # TypeError: unhashable type: dict原因很简单字典是可变的不能直接哈希。怎么解决第一种方案如果你只是想按某个字段去重用seen集合只存那个字段的值而不是整个字典第二种方案如果确实要整体判断字典是否重复可以先把字典转成JSON字符串再放进set但要注意键的顺序问题最好用json.dumps的sort_keysTrue。不过第二种方案有很多边缘情况比如嵌套结构、浮点数精度等复杂业务不建议。5.5 维护性角度去重逻辑要不要封装成函数我自己的建议是凡是去重规则超过一行就封装成函数且函数名里带上“按什么去重、保留哪条”这些语义。比如def dedupe_by_key(items, key_func, keepfirst): seen set() result [] iterable items if keep first else reversed(items) for item in iterable: key key_func(item) if key not in seen: seen.add(key) result.append(item) result.reverse() if keep last else result return result这样调用方一看就懂。生产代码里最怕的开发模式是把去重代码临时写在某个报表脚本里谁都看不懂它按什么规则剔除的重复项。结果三个月后别人改需求误删了一堆数据。封装函数注释写明规则是让项目长期可维护的基本操守。5.6 关于不同语言里“”和“is”对去重的影响这个坑比较硬核但值得说。Python里两个结构相同但内存地址不同的列表用判断是相等的内容比较但is判断是不相等的身份比较。在去重时如果你自己实现了对象数组的相等性判断容易把这两者搞混。JavaScript里两个相同内容的对象用也是不相等的因为对象比较的是引用。所以对象去重一定要自己定义key而不是指望编程语言内置的对象相等。这也是为什么set无法直接处理对象列表的根本原因语言层面的“相等”不一定是业务上的“重复”。6. 一个完整的项目实操案例从零写一个带性能考量的通用去重模块6.1 需求定义假设有这么个任务有一个千万级订单日志的JSON数组每条记录里有order_id字符串、user_id数字、product_id字符串、created_at时间戳。要求按user_id product_id去重每个组合保留created_at最大的那条记录最后输出保序结果。这是一个相当典型的实战任务既涉及去重三问的标准答案唯一性标准是user_idproduct_id保留哪条是created_at最大顺序是原顺序又有性能和数据结构考量。6.2 分步实现第一步读取数据这里简化成列表推导式。第二步明确遍历方向因为要保留created_at最大最稳的办法是同样key先比较时间戳再决定而不是简单逆序。第三步用字典来维护每个key对应的记录如果新记录的created_at更大则覆盖。def dedupe_keep_latest(items, key_func, time_func): best_records {} for item in items: key key_func(item) if key not in best_records or time_func(item) time_func(best_records[key]): best_records[key] item return list(best_records.values())第四步性能检查这里使用了字典做hash存储时间O(n)空间O(n)在千万级数据上内存肯定撑不住所以实际生产环境要配合分桶方案。但思路就是这个思路——保留最大值用“覆盖”策略比“先排序再去重”更清晰。我在实测里遇到过这个模块的两种bug。第一种time_func比较的是字符串导致1577836800被当成时间戳比较全是乱的改成int再比就正常了。第二种key_func里字段存在缺失值比如product_id为空字符串结果所有空商品ID的用户组合都变成同一条去重过头了业务上要求空值不算有效组合于是加了个条件过滤。这类问题你在单元测试里很难发现必须是在真实数据上跑一遍才能暴露。6.3 测试与验证验证去重逻辑对不对我有一套实操经验先手动构造5-6条边界数据含同key不同时间、不同key相同时间、空字段等用assert逐个验证。别等代码跑完了再看结果。比如test_data [ {user_id: 1, product_id: A, created_at: 100}, {user_id: 1, product_id: A, created_at: 200}, {user_id: 1, product_id: B, created_at: 300}, ] assert dedupe_keep_latest(test_data, lambda x: (x[user_id], x[product_id]), lambda x: x[created_at]) [ {user_id: 1, product_id: A, created_at: 200}, {user_id: 1, product_id: B, created_at: 300}, ]测试通过了再去跑真实数据。千万别小看这段基础测试它能省去你后面定位问题的大量时间。7. 我在实际项目中积累的一些心得去重这个功能我在无数个项目里写过踩过的坑比写过的set多得多。最想说的是不要把去重当成一个独立的编程步骤而应该当成数据治理的一部分。去重前先想清楚数据怎么来的、重复是怎么产生的——如果重复是上游接口重复推送导致的光靠下游去重只是亡羊补牢更根治的办法是在源头加幂等控制。如果重复是因为数据库表设计没有唯一索引更合理的解决是给表加联合唯一索引让数据库物理层面杜绝重复。程序里去重永远是兜底方案。第二点心得和“保留哪条”相关。凡是要保留“最新一条”的场景我建议在代码里明确写出比较逻辑而不是依靠列表顺序。因为列表顺序在不同数据源里不可靠你可能从数据库查出来是自然序从消息队列消费出来又变成了乱序。唯一的保底手段就是按时间字段自己比较。第三点心得对比工具效率能交给SQL的去重尽量交给SQL。数据库的优化器配合索引处理亿级数据去重是它就吃饭的本事你把这些数据拉出来在脚本里set简直就是暴殄天物。我见过好些人写个Python脚本从MySQL里select出来一万行到内存里去重转了一圈又写回去。其实直接在SQL里一条GROUP BY就全干完了还能少写很长的判空代码。说白了去重不只是“算法”它还是“架构问题”——在底层去重还是在上层去重性能差别天壤地别。关于“5-7列表去重”——我猜这个题目可能来源于某本教材的章节号也可能读者就是想把5种基础方法到7个进阶技巧连起来看。不管是哪种我希望这篇梳理能帮到你先掌握好set和字典/Map的基本写法再把这些写法迁移到对象数组、SQL、甚至Excel里。把这个技术动作想透你之后写任何代码都会少走一点弯路。
返回列表