iT邦幫忙

2

Python List Comprehension 遇到的疑惑

  • 分享至 

  • xImage

在練習List Comprehension Debug的時候遇到一件事很困惑
目的是要取List裡面各項的第一個字母

country_list=['Aasdf', 'Abasdf', 'Basdf', 'Casdr', 'Dasdf','Elkj']
keys = []

#一般用for loop產生的迴圈
for i in country_list:
    if i[0] not in keys:
        keys.append(i[0])
print(keys)
# ['A', 'B', 'C', 'D', 'E']

keys = [(i[0]) for i in country_list if i[0] not in keys]
print(keys)
# ['A', 'A', 'B', 'C', 'D', 'E']

兩種結果卻不同一直想不透?
請教網上各位 str[index] 與 list.append(str[index]) 究竟有甚麼差別~

froce iT邦大師 1 級 ‧ 2024-01-10 23:16:26 檢舉
這是for迴圈和Comprehension 的不同。
for就一步一步的做,每做一步就會把keys改變一次。keys永遠是同一個。

但你這句
keys = [(i[0]) for i in country_list if i[0] not in keys]
keys只會變動一次,當Comprehension 做完,keys才會指派到新的list上。
也就是python會先生出 ['A', 'A', 'B', 'C', 'D', 'E'],然後keys才會被指派到生出的['A', 'A', 'B', 'C', 'D', 'E']記憶體位置上,這和原本的[]是兩個不同的list。
你可以用id(keys)去看記憶體位置。

不信的話可以改成keys = [print(keys) for i in country_list if i[0] not in keys],看看。
會先跑6次[],最後才會變成[None,None,None,None,None, None ]
謝謝! 你們解釋得非常清楚!
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
1
熊熊工程師
iT邦研究生 1 級 ‧ 2024-01-10 22:36:19
最佳解答

[From GPT]
你遇到的這個問題其實是由於 List Comprehension 中的條件判斷是在創建列表時進行的,導致結果與預期不符。

讓我們來看看這兩個例子:

一般的 For Loop

在這個例子中,keys 列表是逐步構建的。每當新的元素被加入 keys 之後,這個列表就會立即更新。因此,當 if i[0] not in keys 條件被評估時,它是基於當前的 keys 列表。

keys = []
for i in country_list:
    if i[0] not in keys:
        keys.append(i[0])

List Comprehension

而在 List Comprehension 的例子中,當條件 if i[0] not in keys 被評估時,它是基於原始的、未被修改的 keys 列表。也就是說,在整個 List Comprehension 執行過程中,keys 列表不會被更新或改變。這就是為什麼你的 List Comprehension 代碼會重複加入 'A':因為在處理第二個元素 'Abasdf' 時,keys 仍然是空的。

keys = [(i[0]) for i in country_list if i[0] not in keys]

在這個例子中,keys 列表只會在 List Comprehension 執行完畢後才會被賦予新的值,這就導致了你觀察到的不同行為。

解決方法

如果你想使用 List Comprehension 並且避免重複,你可以考慮使用集合(Set)來進行快速的成員資格檢查,並在最後轉換回列表,如下所示:

keys = list({i[0] for i in country_list})

這段代碼首先創建一個集合(Set)來保留所有唯一的首字母,然後將這個集合轉換為列表。這樣可以保證每個字母只會出現一次。

謝謝你超詳細的解答!!

2
meebox
iT邦新手 3 級 ‧ 2024-01-11 12:14:36

你的 list comprehension 寫法實際上等於以下這樣:

>>> keys = []
>>> _keys = [] # list comprehension 建立的新串列
>>> for i in country_list:
...     if not i[0] in keys: # 這裡 keys 都是指向原本的空串列
...         _keys.append(i[0]) # 將首字母加到新建立的串列中
... keys = _keys # 迴圈結束後才會將新串列指派給 keys
>>> keys
['A', 'A', 'B', 'C', 'D', 'E']

所以在比對首字母是否出現在 keys 中時, 這個 keys 都是指向原本的空串列, 導致每一個字串的首字母都會加入到新建立的 _keys 串列中。

0
obarisk
iT邦研究生 1 級 ‧ 2024-01-11 13:32:23

map 沒法完成 map + reduce

0
aurora754
iT邦見習生 ‧ 2024-01-12 03:33:35

List comprehensions are useful and can help you write elegant code that's easy to read and debug, but they're not the right choice for all circumstances. They might make your code run more slowly or use more memory.https://mexicoonlinepharmacy.org/

我要發表回答

立即登入回答