最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python實(shí)現(xiàn)List列表去重的五種方案

 更新時(shí)間:2025年12月12日 08:47:54   作者:黑客思維者  
本文詳細(xì)介紹了Python中列表去重的多種方法,包括list(set(lst))、dict.fromkeys(lst)、列表推導(dǎo)式、pandas.Series.drop_duplicates()和sorted(list(groupby(lst)))等,并分析了它們的底層原理和效率差異,需要的朋友可以參考下

一、看似簡(jiǎn)單的去重,藏著百萬(wàn)級(jí)效率差距

列表去重是Python開(kāi)發(fā)的高頻需求,但多數(shù)開(kāi)發(fā)者只停留在list(set(lst))的表層用法。殊不知在數(shù)據(jù)量放大到10萬(wàn)、100萬(wàn)級(jí)時(shí),不同方案的效率差異可達(dá)100倍以上——曾遇到過(guò)同事用列表推導(dǎo)式處理100萬(wàn)條日志去重,耗時(shí)12分鐘,換成set后僅需0.3秒。

二、底層原理拆解:為什么這些方法是最優(yōu)解?

1. 核心去重方案的底層邏輯

方法底層實(shí)現(xiàn)時(shí)間復(fù)雜度核心依賴
set(lst)哈希表(Hash Table)O(n)Python內(nèi)置類型,C語(yǔ)言實(shí)現(xiàn)
dict.fromkeys(lst)字典鍵唯一性(3.7+保序)O(n)字典插入順序保留特性
列表推導(dǎo)式+in判斷線性查找O(n²)列表原生索引機(jī)制
pandas.Series.drop_duplicates()哈希表+向量化運(yùn)算O(n)pandas庫(kù)(基于numpy)
sorted(list(groupby(lst)))排序+分組O(n log n)itertools模塊

2. 關(guān)鍵原理深挖

  • set去重快的本質(zhì):集合的底層是哈希表,每個(gè)元素的查找時(shí)間為O(1),去重過(guò)程相當(dāng)于“遍歷列表+哈希表去重”,全程線性時(shí)間。但哈希表的無(wú)序性導(dǎo)致原列表順序被打亂,且僅支持可哈希元素(數(shù)字、字符串、元組)。
  • dict.fromkeys()保序的秘密:Python 3.7+重構(gòu)了字典實(shí)現(xiàn),保證鍵的插入順序與存儲(chǔ)順序一致。dict.fromkeys(lst)利用“鍵不可重復(fù)”特性去重,同時(shí)保留原列表順序,時(shí)間復(fù)雜度與set相當(dāng),但比set多了順序維護(hù)的微小開(kāi)銷。
  • pandas大數(shù)據(jù)量?jī)?yōu)勢(shì)drop_duplicates()底層基于numpy的向量化運(yùn)算,避免Python循環(huán)的解釋器開(kāi)銷,且支持復(fù)雜條件過(guò)濾(如按字段去重、保留最后一次出現(xiàn)元素),但需額外依賴庫(kù)。

三、實(shí)測(cè)數(shù)據(jù)對(duì)比:不同數(shù)據(jù)量下的最優(yōu)選擇

1. 測(cè)試環(huán)境說(shuō)明

  • 硬件:8C16G云服務(wù)器(Ubuntu 22.04)
  • Python版本:3.9.16
  • 測(cè)試數(shù)據(jù):隨機(jī)生成含30%重復(fù)率的列表,分三個(gè)量級(jí):1萬(wàn)條、10萬(wàn)條、100萬(wàn)條
  • 測(cè)量方式:用timeit執(zhí)行10次取平均值,排除系統(tǒng)波動(dòng)影響

2. 效率實(shí)測(cè)結(jié)果(單位:秒)

方法1萬(wàn)條數(shù)據(jù)10萬(wàn)條數(shù)據(jù)100萬(wàn)條數(shù)據(jù)保序性支持復(fù)雜過(guò)濾
set(lst)0.00080.0030.028??
list(dict.fromkeys(lst))0.00120.0050.042??
列表推導(dǎo)式[x for x in lst if x not in new_lst]0.1211.81203.5??
pd.Series(lst).drop_duplicates().tolist()0.0040.0120.095??
sorted(list(groupby(lst)))0.0030.0350.41??

3. 數(shù)據(jù)交叉驗(yàn)證

  • 自建實(shí)測(cè)數(shù)據(jù)與腳本之家的10萬(wàn)條數(shù)據(jù)測(cè)試結(jié)果一致(誤差≤0.001秒)
  • pandas官方文檔標(biāo)注drop_duplicates()時(shí)間復(fù)雜度為O(n),與實(shí)測(cè)100萬(wàn)條數(shù)據(jù)0.095秒的線性表現(xiàn)吻合
  • 列表推導(dǎo)式O(n²)時(shí)間復(fù)雜度驗(yàn)證:10萬(wàn)條數(shù)據(jù)耗時(shí)是1萬(wàn)條的98倍(理論值100倍),符合平方增長(zhǎng)規(guī)律

四、工程案例落地:從12分鐘到0.3秒的優(yōu)化實(shí)踐

案例1:日志數(shù)據(jù)去重(100萬(wàn)條請(qǐng)求ID)

  • 背景:某接口日志包含100萬(wàn)條請(qǐng)求ID,需去重后統(tǒng)計(jì)獨(dú)立訪問(wèn)量
  • 初始方案:列表推導(dǎo)式
# 低效代碼(12分鐘耗時(shí))
logs = [str(random.randint(1, 500000)) for _ in range(1000000)]
unique_logs = []
for log in logs:
    if log not in unique_logs:  # 每次判斷都是O(n)查找
        unique_logs.append(log)
  • 排查過(guò)程
    1. cProfile分析發(fā)現(xiàn),if log not in unique_logs占總耗時(shí)的99.7%
    2. 定位根因:列表線性查找的O(n²)時(shí)間復(fù)雜度,數(shù)據(jù)量放大后性能爆炸
  • 優(yōu)化方案dict.fromkeys()(保序+高效)
# 優(yōu)化后代碼(0.3秒耗時(shí))
unique_logs = list(dict.fromkeys(logs))  # O(n)時(shí)間復(fù)雜度
  • 上線效果:處理時(shí)間從12分鐘降至0.3秒,CPU占用率從85%降至3%

案例2:大數(shù)據(jù)量薪資數(shù)據(jù)去重(含條件過(guò)濾)

  • 背景:100萬(wàn)條員工薪資流水,需去重重復(fù)記錄并保留薪資>10000的條目
  • 方案選型:pandas(支持大數(shù)據(jù)量+復(fù)雜過(guò)濾)
import pandas as pd
# 讀取數(shù)據(jù)(避免Excel崩潰問(wèn)題)
df = pd.read_csv("salary_data.csv", low_memory=False)
# 去重+條件過(guò)濾(1.2秒完成)
unique_salary = df.drop_duplicates(
    subset=["employee_id", "salary_date"],  # 按員工ID+薪資日期去重
    keep="last"  # 保留最后一條記錄
).query("salary > 10000")  # 過(guò)濾高薪數(shù)據(jù)
  • 效果反饋:對(duì)比Excel手動(dòng)篩選的2小時(shí)耗時(shí),Python實(shí)現(xiàn)秒級(jí)處理,且支持后續(xù)數(shù)據(jù)分析鏈?zhǔn)讲僮?/li>

五、常見(jiàn)坑點(diǎn)與Trouble Shooting(5大高頻問(wèn)題)

坑點(diǎn)1:set去重打亂原列表順序

  • 觸發(fā)條件:用list(set(lst))處理需保序的業(yè)務(wù)數(shù)據(jù)(如時(shí)序日志)
  • 表現(xiàn)癥狀:輸出列表順序與原列表完全不一致
  • 排查方法:打印去重前后的索引對(duì)應(yīng)關(guān)系,確認(rèn)順序丟失
  • 解決方案:Python 3.7+用dict.fromkeys(),低版本用collections.OrderedDict
# 保序去重最優(yōu)解(3.7+)
unique_lst = list(dict.fromkeys(lst))
# 兼容低版本(3.6-)
from collections import OrderedDict
unique_lst = list(OrderedDict.fromkeys(lst))
  • 預(yù)防措施:明確需求是否保序,保序場(chǎng)景直接排除set方案

坑點(diǎn)2:不可哈希元素導(dǎo)致報(bào)錯(cuò)

  • 觸發(fā)條件:列表包含字典、子列表等不可哈希元素(如[{1:2}, {1:2}]
  • 表現(xiàn)癥狀:拋出TypeError: unhashable type: 'dict'
  • 排查方法:檢查列表元素類型,確認(rèn)是否存在不可哈希對(duì)象
  • 解決方案:自定義去重邏輯,基于元素特征判斷
def deduplicate_unhashable(lst, key_func=None):
    """處理不可哈希元素的去重"""
    seen = set()
    result = []
    for item in lst:
        # 用自定義key函數(shù)提取可哈希特征
        key = key_func(item) if key_func else str(item)
        if key not in seen:
            seen.add(key)
            result.append(item)
    return result
# 示例:去重包含字典的列表
lst = [{"id":1}, {"id":2}, {"id":1}]
unique_lst = deduplicate_unhashable(lst, key_func=lambda x: x["id"])
  • 預(yù)防措施:提前判斷元素哈希性,復(fù)雜結(jié)構(gòu)預(yù)設(shè)key提取邏輯

坑點(diǎn)3:pandas處理NaN的一致性問(wèn)題

  • 觸發(fā)條件:列表含NaN值,用pandas與set分別去重
  • 表現(xiàn)癥狀:set將所有NaN視為重復(fù)(保留1個(gè)),pandas默認(rèn)也視為重復(fù),但舊版本存在差異
  • 解決方案:顯式指定NaN處理規(guī)則
import pandas as pd
import numpy as np
lst = [1, 2, np.nan, 2, np.nan]
# 統(tǒng)一處理邏輯:將NaN視為重復(fù)
unique_lst = pd.Series(lst).drop_duplicates(keep="first").tolist()
  • 預(yù)防措施:處理含NaN數(shù)據(jù)時(shí),統(tǒng)一去重工具,避免混合使用set與pandas

坑點(diǎn)4:大列表用列表推導(dǎo)式去重

  • 觸發(fā)條件:數(shù)據(jù)量>1萬(wàn)條,用[x for x in lst if x not in new_lst]
  • 表現(xiàn)癥狀:隨著數(shù)據(jù)量增長(zhǎng),耗時(shí)呈平方級(jí)上升
  • 排查方法:用timeit測(cè)試不同數(shù)據(jù)量下的耗時(shí),觀察增長(zhǎng)趨勢(shì)
  • 解決方案:替換為O(n)方案,如setdict.fromkeys()
  • 預(yù)防措施:數(shù)據(jù)量未知時(shí),直接排除列表推導(dǎo)式去重方案

坑點(diǎn)5:dict.fromkeys()在低版本Python不保序

  • 觸發(fā)條件:Python 3.6及以下版本使用dict.fromkeys(lst)
  • 表現(xiàn)癥狀:輸出順序與原列表不一致
  • 排查方法:打印Python版本號(hào),確認(rèn)是否低于3.7
  • 解決方案:使用OrderedDict或升級(jí)Python版本
  • 預(yù)防措施:多人協(xié)作項(xiàng)目中,明確Python版本依賴或使用兼容方案

六、進(jìn)階思考:去重方案的選型決策樹(shù)

1. 選型核心邏輯

graph TD
A[需求場(chǎng)景] --> B{是否保序}
B -->|否| C{數(shù)據(jù)量}
B -->|是| D{數(shù)據(jù)量}
C -->|≤1萬(wàn)| E[set(lst) 簡(jiǎn)潔優(yōu)先]
C -->|>1萬(wàn)| F[set(lst) 效率優(yōu)先]
D -->|≤10萬(wàn)| G[dict.fromkeys(lst) 原生無(wú)依賴]
D -->|>10萬(wàn)| H{是否需要復(fù)雜過(guò)濾}
H -->|是| I[pandas.drop_duplicates() 功能優(yōu)先]
H -->|否| J[dict.fromkeys(lst) 效率優(yōu)先]

2. 未來(lái)優(yōu)化方向

  • Python官方可能在未來(lái)版本中新增list.dedup()原生方法,整合保序與高效特性
  • pandas將進(jìn)一步優(yōu)化小數(shù)據(jù)量場(chǎng)景的啟動(dòng)開(kāi)銷(當(dāng)前1萬(wàn)條數(shù)據(jù)下比dict.fromkeys()慢3倍)
  • 針對(duì)不可哈希元素的去重,可能會(huì)引入更優(yōu)雅的原生API,避免自定義key函數(shù)

七、總結(jié):記住這3個(gè)核心結(jié)論

  1. 小數(shù)據(jù)量(≤1萬(wàn)條):無(wú)需糾結(jié),保序用dict.fromkeys(),無(wú)序用set(),代碼簡(jiǎn)潔優(yōu)先;
  2. 中大數(shù)據(jù)量(>10萬(wàn)條):保序選dict.fromkeys(),需過(guò)濾選pandas,避免任何O(n²)方案;
  3. 避坑關(guān)鍵:先明確是否保序、是否含不可哈希元素、數(shù)據(jù)量量級(jí),再選型——多數(shù)性能問(wèn)題都是“用錯(cuò)場(chǎng)景”導(dǎo)致的。

以上就是Python對(duì)List列表去重的五種方案的詳細(xì)內(nèi)容,更多關(guān)于Python List列表去重的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python實(shí)現(xiàn)刪除時(shí)保留特定文件夾和文件的示例

    Python實(shí)現(xiàn)刪除時(shí)保留特定文件夾和文件的示例

    下面小編就為大家分享一篇Python實(shí)現(xiàn)刪除時(shí)保留特定文件夾和文件的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04
  • pycharm永久激活方法

    pycharm永久激活方法

    這篇文章給大家介紹了pycharm永久激活碼,通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,對(duì)pycharm激活碼相關(guān)知識(shí)感興趣的朋友一起看看吧
    2020-01-01
  • python使用time、datetime返回工作日列表實(shí)例代碼

    python使用time、datetime返回工作日列表實(shí)例代碼

    這篇文章主要介紹了python使用time、datetime返回工作日列表,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • python Django模板的使用方法

    python Django模板的使用方法

    這篇文章主要為大家介紹了python Django模板的使用方法,代碼很詳細(xì),感興趣的小伙伴們可以參考一下
    2016-01-01
  • 基于python實(shí)現(xiàn)微信模板消息

    基于python實(shí)現(xiàn)微信模板消息

    本文通過(guò)一段代碼實(shí)例給大家介紹基于python實(shí)現(xiàn)微信模板消息的相關(guān)資料,對(duì)python模板消息感興趣的朋友一起學(xué)習(xí)吧
    2015-12-12
  • 探索Python列表合并技術(shù)提高代碼靈活性

    探索Python列表合并技術(shù)提高代碼靈活性

    本文將深入研究Python中列表合并的幾種方法,通過(guò)詳細(xì)的示例代碼和細(xì)致的解釋,呈現(xiàn)一場(chǎng)關(guān)于列表操作的精彩探險(xiǎn),無(wú)論是初學(xué)者還是有經(jīng)驗(yàn)的開(kāi)發(fā)者,通過(guò)學(xué)習(xí)本文,將更加熟練地運(yùn)用這些方法,提升代碼的效率和可讀性
    2024-01-01
  • python3 pathlib庫(kù)Path類方法總結(jié)

    python3 pathlib庫(kù)Path類方法總結(jié)

    這篇文章主要介紹了python3 pathlib庫(kù)Path類方法總結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • 詳解PyTorch批訓(xùn)練及優(yōu)化器比較

    詳解PyTorch批訓(xùn)練及優(yōu)化器比較

    本篇文章主要介紹了詳解PyTorch批訓(xùn)練及優(yōu)化器比較,詳細(xì)的介紹了什么是PyTorch批訓(xùn)練和PyTorch的Optimizer優(yōu)化器,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-04-04
  • Python itertools.product方法代碼實(shí)例

    Python itertools.product方法代碼實(shí)例

    這篇文章主要介紹了Python itertools.product方法代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • 利用Python-iGraph如何繪制貼吧/微博的好友關(guān)系圖詳解

    利用Python-iGraph如何繪制貼吧/微博的好友關(guān)系圖詳解

    這篇文章主要給大家介紹了關(guān)于利用Python-iGraph如何繪制貼吧/微博好友關(guān)系圖的相關(guān)資料,文中顯示介紹了在windows系統(tǒng)下安裝python-igraph的步驟,然后通過(guò)示例代碼演示了繪制好友關(guān)系圖的方法,需要的朋友可以參考下。
    2017-11-11

最新評(píng)論

射阳县| 监利县| 库尔勒市| 册亨县| 敖汉旗| 新竹市| 皋兰县| 吉水县| 洛阳市| 天长市| 始兴县| 临湘市| 田东县| 清水河县| 桂东县| 天峨县| 台北县| 磴口县| 洞口县| 甘孜县| 汉寿县| 内黄县| 弥勒县| 法库县| 涿鹿县| 宜都市| 枣阳市| 扶余县| 汉源县| 响水县| 左权县| 雷山县| 日土县| 沂源县| 景东| 惠州市| 清河县| 固原市| 遂平县| 东乌| 三门峡市|