列表(List)是 Python 中重要的一種容器(Container),在 #雙週Python程式設計非入門挑戰 中,我們也設計關於列表的思考題:

如果想要從列表中如果想要挑選出 #重複出現 的元素有哪幾個,該如何實作?

關於這個題目,在 Facebook 的原始討論串中有蠻多的分享,歡迎大家查閱。這一篇想跟大家分享我自己準備好的想法跟方法。

題目描述

講到不重複去除重複之類的關鍵字,很直覺地會想到「集合(Set)」的容器型態與其特性。但如果我們只想挑出重複出現過的元素而非去除重複的話,該怎麼實作?

  • Sample Input #1: [1, 3, 1, 2, 2, 4, 5, 3]
  • Sample Output #1: [1, 2, 3]
  • Sample Input #2: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
  • Sample Output #2: [1]

解題思路

本題要求只想挑出重複出現過的元素,使用集合(Set)是直接無法判斷的,必須手動紀錄出現超過一次的元素。

參考解答

方法一:新手也應該想得到的方法

順著解題思路,利用判斷的迴圈的方法可以輕鬆實現:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def f1(L):
d = {}
L2 = []
for e in L:
d[e] = d.get(e, 0) + 1
if d[e] > 1 and e not in L2:
L2.append(e)
return L2

L1 = [1, 3, 1, 2, 2, 4, 5, 3]
print(f1(L1)) # [1, 2, 3]

L2 = [1, 1, 1, 1, 1, 1, 1, 1]
print(f1(L2)) # [1]

方法二:利用 List 中的 count() 方法

第一種方法需要對每個元素都一個一個看過一次,不過如果有印象 List 中有一個 count(…) 方法的話,就可以省略到每個元素都檢查的動作:

1
2
3
4
5
6
7
8
9
10
11
12
def f2(L):
L2 = []
for e in set(L):
if L.count(e) > 1:
L2.append(e)
return L2

L1 = [1, 3, 1, 2, 2, 4, 5, 3]
print(f2(L1)) # [1, 2, 3]

L2 = [1, 1, 1, 1, 1, 1, 1, 1]
print(f2(L2)) # [1]

方法三: 善用 List Comprehension 優化 Python 程式

只要看到對 List 進行簡單的回圈運算,都可以試著用 Comprehension 進行改寫,程式碼會看起來簡潔一點:

1
2
3
4
5
6
7
8
def f3(L):
return [e for e in set(L) if L.count(e) > 1]

L1 = [1, 3, 1, 2, 2, 4, 5, 3]
print(f3(L1)) # [1, 2, 3]

L2 = [1, 1, 1, 1, 1, 1, 1, 1]
print(f3(L2)) # [1]

方法四: Counter 是個好用的工具

順著方法二的 count(…) 方法,更進階一點可以利用 collections 當中的 Counter 方法做到比較複雜的計數功能:

1
2
3
4
5
6
7
8
9
10
11
from collections import Counter

def f4(L):
tmp = dict(Counter(L))
return [k for (k,v) in tmp.items() if v > 1]

L1 = [1, 3, 1, 2, 2, 4, 5, 3]
print(f4(L1)) # [1, 2, 3]

L2 = [1, 1, 1, 1, 1, 1, 1, 1]
print(f4(L2)) # [1]

方法五: 利用 List 與 Set 的特性炫技

最後一個想到的想法還是回到 List 與 Set 的原始特性,搭配一些技巧就可以寫出很炫炮的解法:

1
2
3
4
5
6
7
8
9
def f5(L):
L.sort()
return list(set(L[::2]) & set(L[1::2]))

L1 = [1, 3, 1, 2, 2, 4, 5, 3]
print(f5(L1)) # [1, 2, 3]

L2 = [1, 1, 1, 1, 1, 1, 1, 1]
print(f5(L2)) # [1]

回顧與反饋

以上大概就是關於 只想挑出重複出現過的元素 題目的一些方法,我覺得「優化」其實是程式能力鍛鍊的重要方法。而「如何優化」會建議透過不同等級的方法來練習跟參考,先試著用自己想得到方法來完成要求、再進一步觀摩不同的寫法,持續為之。




嗨,我是維元,近期推出一個全新型態的【 Python 資料科學教學實戰營 】,結合多元教學形式及豐富課程經驗幫助你更有效地學習。新課程「徒手打造數據分析應用案例 」正在早鳥募資中,歡迎你一起加入資料領域!誠摯的邀請你跟著我們一起從 Python 入門開始,走進資料科學的世界 🙌



📍 報名頁面: https://pse.is/44kvze
📍 報名頁面: https://pse.is/44kvze
📍 報名頁面: https://pse.is/44kvze

另外我也持續在不同的平台發表對 #資料科學、 #網頁開發 或 #軟體職涯 相關的文章。如果對於內文有疑問都歡迎與我們進一步的交流,都可以追蹤資料科學家的工作日常 Facebook 粉專Instagram 帳號,也會不定時的舉辦分享活動,一起來玩玩吧!


License


本著作由Chang Wei-Yaun (v123582)製作,
創用CC 姓名標示-相同方式分享 3.0 Unported授權條款釋出。