1.10 刪除序列中的重複元素並保持順序
阿新 • • 發佈:2021-12-25
怎樣在一個序列上面保持元素順序的同時消除重複的值?
問題描述
怎樣在一個序列上面保持元素順序的同時消除重複的值?
解決方案
如果序列上的值都是hashable
型別(簡言之,python中不可變物件就是hashable
型別的,具體介紹參考官方文件),那麼可以很簡單的利用集合或者生成器解決這個問題:
def dedupe(items): seen = set() for item in items: if item not in seen: yield item seen.add(item) a = [1, 5, 2, 1, 9, 1, 5, 10] res = list(dedupe(a)) # res = [1, 5, 2, 9, 10]
這個方法僅在序列元素為hashable
時可用。如果你想消除元素不可雜湊的序列(比如dict)中重複元素的話,需要將上述程式碼稍作修改:
def dedupe(items, key=None): """ 這裡的key引數指定了一個函式,將items中元素轉化成了hashable型別。 """ seen = set() for item in items: val = item if key is None else key(item) if val not in seen: yield item seen.add(val) return seen a = [{'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 1, 'y': 2}, {'x': 2, 'y': 4}] res = list(dedupe(a, key=lambda d: (d['x'], d['y']))) # res = [{'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 2, 'y': 4}] re = list(dedupe(a, key=lambda d: (d['x']))) # re = [{'x': 1, 'y': 2}, {'x': 2, 'y': 4}]
討論
如果你只想消除重複元素,通常可以簡單的構造一個集合。比如:
a = [1, 5, 2, 1, 9, 1, 5, 10]
res = set(a)
# res = {1, 2, 5, 9, 10}
然而這種方法不能維護元素的順序。
在本節中,我們使用了生成器函式讓我們的函式更加通用,不僅僅是侷限於列表處理。比如,如果你想讀取一個檔案,消除重複行,你可以這樣做:
with open(file, 'r') as f:
for line in dedupe(f):
...
上述key
函式引數模仿了sorted()
,min()
和max()
等內建函式的相似功能。可以參考1.8和1.13小節瞭解更多。