在 Python 中,“按值批量刪除” 並 “去重” 的核心是 先篩選出不需要刪除的元素,再通過集合(set)自動去重。以下是 4 種常用實現方式,覆蓋不同場景(是否保留原順序、是否修改原列表、效率要求),附帶代碼示例和詳細解析:

一、核心需求拆解

  • 按值批量刪除:給定要刪除的多個值(如 [2,3,5]),從列表中移除所有匹配的元素;
  • 去重:最終結果列表中不包含重複元素(即使原列表有重複的保留元素);
  • 可選需求:是否保留原列表的元素順序、是否允許修改原列表、是否需要高效處理大數據量。

二、4 種實現方式(按推薦優先級排序)

方式 1:列表推導式 + set(推薦,保留順序 + 高效)

核心邏輯

用列表推導式篩選出 “不在刪除值列表” 中的元素,再通過 dict.fromkeys() 或 OrderedDict 去重並保留原順序(Python 3.7+ 後 dict 有序)。

代碼示例

python

運行

# 原列表
nums = [1, 2, 3, 2, 4, 5, 5, 6, 3, 7, 7]
# 要刪除的值
del_values = {2, 3, 5}  # 用 set 存儲,查找效率 O(1)(推薦)

# 步驟 1:篩選出不刪除的元素(保留原順序)
filtered = [x for x in nums if x not in del_values]
# 步驟 2:去重並保留原順序(Python 3.7+)
result = list(dict.fromkeys(filtered))  # dict.fromkeys() 自動去重,保留插入順序

print(result)  # 輸出:[1, 4, 6, 7](保留原順序,無重複)

原理

  • 列表推導式 [x for x in nums if x not in del_values]:遍歷原列表,僅保留不在 del_values 中的元素(保留原順序),時間複雜度 O (n);
  • dict.fromkeys(filtered):用篩選後的列表作為字典的鍵,字典的鍵自動去重,且 Python 3.7+ 後保留鍵的插入順序(即原列表順序),時間複雜度 O (m)(m 為篩選後列表長度);
  • 整體時間複雜度 O (n + m) = O (n)(高效)。

優點

  • 保留原元素順序(符合日常需求);
  • 效率高(篩選和去重都是線性時間);
  • 語法簡潔,一行可完成(合併步驟):
    python
    運行
result = list(dict.fromkeys([x for x in nums if x not in del_values]))

適用場景

  • 日常開發中 “按值批量刪 + 去重 + 保留順序” 的核心場景(90% 以上場景適用)。

方式 2:set 差集(最快,不保留順序)

核心邏輯

將原列表和刪除值列表都轉為 set,通過集合差集直接獲取 “保留的元素”,再轉回列表(set 自動去重,但無序)。

代碼示例

python

運行

nums = [1, 2, 3, 2, 4, 5, 5, 6, 3]
del_values = {2, 3, 5}

# 步驟 1:轉為 set,求差集(自動去重+刪除指定值)
result_set = set(nums) - del_values  # 差集:nums 中不在 del_values 的元素
# 步驟 2:轉回列表(無序)
result = list(result_set)

print(result)  # 輸出:[1, 4, 6](順序不固定,自動去重)

原理

  • set(nums):原列表轉集合,自動去重(時間複雜度 O (n));
  • set(nums) - del_values:集合差集運算,獲取保留的元素(時間複雜度 O (min (n, k)),k 為刪除值個數);
  • 整體時間複雜度 O (n),是所有方式中最快的。

優點

  • 速度極快(集合運算底層優化);
  • 代碼極簡(一行可完成):
    python
    運行
result = list(set(nums) - {2, 3, 5})

缺點

  • 不保留原列表的元素順序(set 是無序結構);
  • 自動去重(若需保留重複元素,不適用)。

適用場景

  • 無需保留原順序,僅需 “快速刪除指定值 + 去重” 的場景(如數據清洗、標籤過濾)。

方式 3:倒序遍歷 + pop ()(修改原列表,保留順序)

核心邏輯

倒序遍歷原列表,若元素在刪除值列表中,用 pop() 刪除(倒序避免索引錯亂),同時用 set 記錄已保留的元素,實現去重。

代碼示例

python

運行

nums = [1, 2, 3, 2, 4, 5, 5, 6, 3, 7, 7]
del_values = {2, 3, 5}
seen = set()  # 記錄已保留的元素,用於去重

# 倒序遍歷(索引從 len(nums)-1 到 0)
for i in range(len(nums)-1, -1, -1):
    current = nums[i]
    # 條件:1. 元素不在刪除值列表;2. 元素未被保留過(去重)
    if current in del_values or current in seen:
        nums.pop(i)  # 刪除元素(倒序不影響索引)
    else:
        seen.add(current)  # 記錄已保留的元素

print(nums)  # 輸出:[1, 4, 6, 7](保留原順序,修改原列表)

原理

  • 倒序遍歷:避免正序刪除導致的索引偏移(刪除後面的元素不影響前面的索引);
  • seen 集合:記錄已保留的元素,再次出現時直接刪除(實現去重);
  • pop(i):刪除當前索引元素,時間複雜度 O (n)(非末尾元素需移動後續元素),但因倒序,移動次數較少。

優點

  • 直接修改原列表(無額外內存佔用,適合大數據量);
  • 保留原元素順序。

缺點

  • 時間複雜度 O (n²)(最壞情況,如刪除大量元素時多次 pop 移動);
  • 代碼較繁瑣(需維護 seen 集合和倒序遍歷)。

適用場景

  • 需修改原列表,且內存敏感(如超大列表,無法生成新列表)的場景。

方式 4:pandas 庫(大數據量 + 高效,保留順序)

核心邏輯

利用 pandas 庫的 Series 數據結構,通過 isin() 篩選元素,drop_duplicates() 去重,適合處理十萬級以上的大數據量。

代碼示例

python

運行

import pandas as pd

nums = [1, 2, 3, 2, 4, 5, 5, 6, 3, 7, 7] * 1000  # 放大為 11000 個元素(模擬大數據)
del_values = {2, 3, 5}

# 步驟 1:轉為 pandas Series
s = pd.Series(nums)
# 步驟 2:篩選出不在刪除值列表的元素
filtered = s[~s.isin(del_values)]  # ~ 表示取反
# 步驟 3:去重並保留原順序
result = filtered.drop_duplicates().tolist()

print(result)  # 輸出:[1, 4, 6, 7](保留原順序,高效處理大數據)

原理

  • s.isin(del_values):判斷每個元素是否在刪除值列表中,返回布爾 Series(時間複雜度 O (n));
  • s[~s.isin(del_values)]:篩選出不刪除的元素(保留原順序);
  • drop_duplicates():去重並保留首次出現的元素(時間複雜度 O (n));
  • pandas 底層用 C 語言優化,大數據量下效率遠高於純 Python 方法。

優點

  • 大數據量處理極快(十萬級以上元素優勢明顯);
  • 保留原順序,語法簡潔。

缺點

  • 需安裝 pandas 庫(非 Python 內置);
  • 小數據量下(如幾百個元素),因庫調用開銷,效率不如方式 1 和 2。

適用場景

  • 數據分析、大數據處理場景(如處理 CSV 數據、日誌數據中的批量刪除 + 去重)。

三、不同場景的最優選擇

場景描述

推薦方式

核心優勢

日常場景(保留順序 + 高效 + 簡潔)

方式 1(列表推導式 + set)

兼顧順序、效率和簡潔性,適用面廣

無需保留順序(追求最快速度)

方式 2(set 差集)

速度極快,代碼極簡

內存敏感(超大列表,修改原列表)

方式 3(倒序遍歷 + pop)

無額外內存佔用

大數據量(十萬級以上,保留順序)

方式 4(pandas)

底層優化,效率遠超純 Python

四、避坑重點

  1. 刪除值用 set 存儲:無論哪種方式,del_values 建議用 set(如 {2,3,5}),而非列表([2,3,5])——in 操作在 set 中是 O (1),列表中是 O (k)(k 為刪除值個數),大數據量下差異明顯;
  2. 避免正序遍歷刪除:如 for num in nums: if num in del_values: nums.remove(num),會導致索引偏移,元素漏刪,且無法實現去重;
  3. 去重並保留順序的關鍵:Python 3.7+ 用 dict.fromkeys(),Python 3.6 及以下用 collections.OrderedDict.fromkeys()(功能一致);
  4. pandas 適用於大數據:小數據量(如幾千個元素)用方式 1 即可,無需引入 pandas(避免庫依賴和調用開銷)。

五、總結

  • 日常開發優先選 方式 1(列表推導式 + set) ,兼顧順序、效率和簡潔性;
  • 追求極致速度且無需順序選 方式 2(set 差集)
  • 內存敏感或必須修改原列表選 方式 3(倒序遍歷 + pop)
  • 大數據量處理選 方式 4(pandas)

根據實際需求(是否保留順序、數據量、內存限制)選擇合適的方式,即可高效實現 “按值批量刪 + 去重”。