1.19 轉(zhuǎn)換并同時(shí)計(jì)算數(shù)據(jù)

2018-02-24 15:26 更新

問題

你需要在數(shù)據(jù)序列上執(zhí)行聚集函數(shù)(比如 sum() , min() , max() ),但是首先你需要先轉(zhuǎn)換或者過濾數(shù)據(jù)

解決方案

一個(gè)非常優(yōu)雅的方式去結(jié)合數(shù)據(jù)計(jì)算與轉(zhuǎn)換就是使用一個(gè)生成器表達(dá)式參數(shù)。比如,如果你想計(jì)算平方和,可以像下面這樣做:

nums = [1, 2, 3, 4, 5]
s = sum(x * x for x in nums)

下面是更多的例子:

# Determine if any .py files exist in a directory
import os
files = os.listdir('dirname')
if any(name.endswith('.py') for name in files):
    print('There be python!')
else:
    print('Sorry, no python.')
# Output a tuple as CSV
s = ('ACME', 50, 123.45)
print(','.join(str(x) for x in s))
# Data reduction across fields of a data structure
portfolio = [
    {'name':'GOOG', 'shares': 50},
    {'name':'YHOO', 'shares': 75},
    {'name':'AOL', 'shares': 20},
    {'name':'SCOX', 'shares': 65}
]
min_shares = min(s['shares'] for s in portfolio)

討論

上面的示例向你演示了當(dāng)生成器表達(dá)式作為一個(gè)單獨(dú)參數(shù)傳遞給函數(shù)時(shí)候的巧妙語(yǔ)法(你并不需要多加一個(gè)括號(hào))。比如,下面這些語(yǔ)句是等效的:

s = sum((x * x for x in nums)) # 顯示的傳遞一個(gè)生成器表達(dá)式對(duì)象
s = sum(x * x for x in nums) # 更加優(yōu)雅的實(shí)現(xiàn)方式,省略了括號(hào)

使用一個(gè)生成器表達(dá)式作為參數(shù)會(huì)比先創(chuàng)建一個(gè)臨時(shí)列表更加高效和優(yōu)雅。比如,如果你不使用生成器表達(dá)式的話,你可能會(huì)考慮使用下面的實(shí)現(xiàn)方式:

nums = [1, 2, 3, 4, 5]
s = sum([x * x for x in nums])

這種方式同樣可以達(dá)到想要的效果,但是它會(huì)多一個(gè)步驟,先創(chuàng)建一個(gè)額外的列表。對(duì)于小型列表可能沒什么關(guān)系,但是如果元素?cái)?shù)量非常大的時(shí)候,它會(huì)創(chuàng)建一個(gè)巨大的僅僅被使用一次就被丟棄的臨時(shí)數(shù)據(jù)結(jié)構(gòu)。而生成器方案會(huì)以迭代的方式轉(zhuǎn)換數(shù)據(jù),因此更省內(nèi)存。

在使用一些聚集函數(shù)比如 min()max() 的時(shí)候你可能更加傾向于使用生成器版本,它們接受的一個(gè)key關(guān)鍵字參數(shù)或許對(duì)你很有幫助。比如,在上面的證券例子中,你可能會(huì)考慮下面的實(shí)現(xiàn)版本:

# Original: Returns 20
min_shares = min(s['shares'] for s in portfolio)
# Alternative: Returns {'name': 'AOL', 'shares': 20}
min_shares = min(portfolio, key=lambda s: s['shares'])
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)