HI,大家好,我是星光。
近幾年來,Excel函數(shù)做了兩次變革。第1次變革是動態(tài)數(shù)組,極大提高了函數(shù)的計算效率,它的核心函數(shù)是FILTER。第2次變革是編程式函數(shù)體系,用編程的方式分步驟編寫函數(shù),用顯性循環(huán)替代之前的數(shù)組運算。
這批函數(shù)包含了我們之前分享過的LET/SCAN/BYROW/MAP/VSTACK等等,它們也有一個核心函數(shù),就是今天要給大家分享的REDUCE。
▎基礎語法
REDUCE函數(shù)只有3個參數(shù),看起來簡單而單純。
=REDUCE([initial_value], array,
lambda(accumulator, value))
第1個參數(shù)是初始累加值,第2個參數(shù)是源數(shù)組,第3個參數(shù)是LAMBDA表達式自定義計算方式,它又有兩個參數(shù),其中acc指向'初始累加值',value指向源數(shù)組每個被遍歷的元素。
先舉一個簡單的例子,給大家演示下該函數(shù)的計算過程。
如上圖所示的數(shù)據(jù)表,A列是班級、B列是姓名。假設,現(xiàn)在需要統(tǒng)計1班的人數(shù),REDUCE的解法如下:
=REDUCE(0,A2:A8,
LAMBDA(_p,_v,
IF(_v='1班',_p+1,_p)
)
)
REDUCE第1參數(shù)為0,表示初始值為0,第2參數(shù)為A2:A8,第3參數(shù)是一個LAMBDA表達式,有兩個參數(shù)_p和_v,其中_p作為初始值,目前為0,_v指向REDUCE的第2參數(shù),即A2:A8。
LAMBDA遍歷A2:A8每一個值,運行表達式IF(_v='1班',_p+1,_p)。
A2單元格為1班,則條件成立,返回結(jié)果_p+1,即0+1,結(jié)果為1,作為LAMBDA新的第1參數(shù),也就是新的初始值。
A3單元格為1班,則條件成立,返回結(jié)果_p+1,即1+1,結(jié)果為2,作為LAMBDA新的第1參數(shù),也就是新的初始值。
A4單元格為2班,則條件不成立,返回結(jié)果_p,即2,作為LAMBDA新的第1參數(shù)。
……
依次類推,直至遍歷完A2:A8的所有元素,將LAMBDA第1參數(shù)的值返回,結(jié)果為3?!绻阌蠱函數(shù)或者JS函數(shù)的學習經(jīng)驗,對該計算方式應該是秒懂的。
以上的案例是條件計數(shù),同樣的道理,我們還可以用REDUCE解決條件查詢、條件求和等問題。
REDUCE條件求和
統(tǒng)計1班成績總分: ▼
=REDUCE(0,ROW(2:8),
LAMBDA(_p,_v,
IF(
INDEX(A:A,_v)='1班',
_p+INDEX(D:D,_v),
_p
)
)
)
REDUCE條件查詢
查詢1班人員名單 ▼
=REDUCE('',ROW(2:8),
LAMBDA(_p,_v,
IF(
INDEX(A:A,_v)='1班',
_p&' ' &INDEX(B:B,_v),
_p
)
)
)
……
▎常用情景
打個響指,條件查詢/求和/計數(shù)這些常見問題,Excel都封裝了專門的函數(shù),比如COUNTIF/SUMIF/TEXTJOIN等,在單值查詢的情況下,并不需要使用REDUCE函數(shù),以上只是通過你熟悉的例子,來說明REDUCE的計算過程。
最常使用REDUCE函數(shù)的情景有兩種,一種是必須借助該函數(shù)的特性去解決的問題,另外一種還是借助該函數(shù)的特性,以動態(tài)數(shù)組的形式,用一條函數(shù)公式,實現(xiàn)多值數(shù)據(jù)計算,這可以極大提高函數(shù)的計算效率。
先看第1種情景,我舉2個典型的案例。
1)多表匯總
如下圖所示,有3張工作表,名稱分別為一月、二月、三月,現(xiàn)在需要將3張表的數(shù)據(jù)合并成一張總表。
REDUCE解法如下:
公式看不全可以左右拖動..
=REDUCE(
{'班級','姓名','成績'},
{'一月','二月','三月'},
LAMBDA(_p,_v,
VSTACK(_p,
DROP(
INDIRECT(_v&'!a1:c' & COUNTA(INDIRECT(_v&'!a:a'))),1)
)
)
)
REDUCE第1參數(shù)是標題行,第2參數(shù)是需要合并的工作表的表名。LAMBDA表達式遍歷每張工作表,使用INDIRECT函數(shù)獲取相關(guān)工作表的實際數(shù)據(jù)區(qū)域,再使用DROP函數(shù)刪除重復的標題行,最后使用VSTACK函數(shù)將新工作表的數(shù)據(jù)和累加值_p合并,實現(xiàn)多表數(shù)據(jù)合并的目的。
2)多重替換
如下圖所示,D:E是對照表,現(xiàn)在需要將A列數(shù)據(jù)中的舊數(shù)據(jù)替換為對應的新數(shù)據(jù),比如,把A替換為福建,B替換為廣西等等。
B2單元格輸入以下REDUCE函數(shù)公式,向下復制填充:
=REDUCE(
A2,
$D$2:$D$5,
LAMBDA(_p,_v,
SUBSTITUTE(_p,_v,
VLOOKUP(_v,D:E,2,0)
)
)
)
LAMBDA遍歷REDUCE第2參數(shù)D2:D5中的每個值,將舊數(shù)據(jù)替換為VLOOKUP匹配的新數(shù)據(jù),不斷累加替換,直至將D2:D5單元格中每個舊數(shù)據(jù)都替換完畢,返回最后的累加值_p即可。
……
但這種在每個單元格都反復編寫函數(shù)公式的方式,會極大拖累函數(shù)的計算效率,它會反復將單元格區(qū)域的數(shù)據(jù),比如D2:E5,讀入內(nèi)存中執(zhí)行計算,再將計算結(jié)果多次寫入單元格中。
理想的計算方式是我們之前講過的動態(tài)數(shù)組,用一次戰(zhàn)爭解決所有戰(zhàn)爭,用一條函數(shù)公式,返回全部結(jié)果。這就是我們前面說的REDUCE的第2種應用場景了。
以多重替換案例來說,可以在B2單元格輸入以下動態(tài)數(shù)組公式,直接返回全部結(jié)果:
=MAP(A2:A3,LAMBDA(_m,
REDUCE(_m,D2:D5,
LAMBDA(_p,_v,
SUBSTITUTE(_p,_v,
VLOOKUP(_v,D:E,2,0)
)))))
在上述公式中,我們在REDUCE外又嵌套了個MAP函數(shù),用于遍歷A2:A3的數(shù)據(jù),并返回相應的計算結(jié)果。
但MAP函數(shù)有一個強規(guī)則,它返回的結(jié)果數(shù)組和數(shù)據(jù)源數(shù)組的尺寸必然保持一致。而相比之下,REDUCE函數(shù)則自由的多,它并沒有這類限制,也就更適合搭配動態(tài)數(shù)組高效解決問題。
還是舉個例子。
如下圖所示,A列是由混合文本組成的數(shù)據(jù),需要從中提取班級、姓名、性別、語文、數(shù)學和英語等信息。C:H列是模擬結(jié)果。
函數(shù)參考解法如下:
=LET(
_n,{'班級','姓名','性別','語文','Math','EngLish'},
REDUCE(_n,A2:A3,LAMBDA(_p,_v,
VSTACK(_p,
IFNA(
VLOOKUP(_n,
TEXTSPLIT(_v,':',CHAR(10)),2,),
'查無')
)
)
)
)
函數(shù)首先定義了一個變量_n,內(nèi)容是標題信息。
{'班級','姓名','性別','語文','Math','EngLish'}
然后使用REDUCE函數(shù)遍歷A2:A3。在遍歷過程中,使用TEXTSPLIT函數(shù)將數(shù)據(jù)按':'和換行符拆分為由項和內(nèi)容構(gòu)成的二維數(shù)組,比如A2單元格拆分結(jié)果如下:
使用VLOOKUP函數(shù),查詢標題在以上二維數(shù)組中的值,如果查無結(jié)果,則返回字符串'查無'。這里返回的結(jié)果是一個水平一維數(shù)組:
將水平數(shù)組和REDUCE的初始值通過VSTACK函數(shù)縱向合并,得到一個新的初始值,結(jié)果如下:
然后再計算A3單元格,將計算結(jié)果和之前的初始值合并:
至此就將源數(shù)組所有元素遍歷完了,將LAMBDA第1參數(shù)作為結(jié)果返回。
攤手,就這么回事。
以上只是給大家介紹了下REDUCE各種用法中的極小且簡單的部分,該函數(shù)除了用于數(shù)據(jù)查詢、統(tǒng)計、排名,也常用于數(shù)據(jù)整理、結(jié)構(gòu)轉(zhuǎn)換等等。你幾乎可以在任何復雜的函數(shù)問題中見到它的身影。
更多REDUCE函數(shù)的實戰(zhàn)案例,可以參考我們的100道練習題系列,這個練習題系列的解法不但包含了工作表函數(shù),也包含了VBA/JS/PQ/PP/SQL以及Python等常用表格技術(shù)。
聯(lián)系客服