化于無形的 lambda 語法

針對數據集合的每個成員進行計算是很常見的任務,用循環語句當然能實現,但比較麻煩,算個簡單的求和都要寫很多句代碼。

編程語言經常把這些運算封裝成函數,比如 Python 的 sum 函數,求訂單價格總和是這樣寫的:

total_price = orders['price'].sum()

SQL 也可以寫成:

select sum(price) total_price from orders

SPL 當然也沒問題:

total_price = orders.sum(price)

看起來都很簡潔。

任務當然不會總是這么簡單,看一個更復雜的例子:對員工計算標簽列,薪酬在 5000 以上的經理標簽為 yes,其他員工為 no。

這個計算可以用一個不太復雜的表達式來描述,但不能在循環外部事先計算出結果,而要在循環中針對每個集合成員計算。這時候,可以把這個表達式定義成函數,再把這個函數作為參數傳遞給循環計算的函數,Python 可以這么寫:

def calc_flag(row):
return 'yes' if row['position'] == 'manager' and row['salary'] > 5000 else 'no'employee['flag']=employee.apply(calc_flag, axis=1)

這段代碼先定義了一個函數 calc_flag,對傳入的記錄 row 計算表達式。

apply 函數以 calc_flag 為參數,在循環中將集合的當前成員(記錄)傳遞給 calc_flag 計算,并用結果組成新序列。

顯然,每次都預先定義成一個函數實在是麻煩,特別是對這么一個簡單表達式就能搞定的任務。于是業界發明了 lambda 語法,可以在參數中定義函數,代碼簡潔很多:

employee['flag'] = employee.apply(lambda row: 'yes' if row['position'] == 'manager' and row['salary'] > 5000 else 'no', axis=1)

apply 函數的參數中用 lambda 關鍵字定義了一個匿名函數,傳入參數是記錄 row。在循環過程中,apply 函數將每個成員(記錄)傳給 lambda 函數,計算得到新的序列。

Python 的這種寫法是顯式的 lambda 語法,有 lambda 關鍵字,要定義參數,還要寫函數體。

SQL 又是如何處理這種問題的呢?

SELECT *,CASE WHEN position = 'manager' AND salary > 5000 THEN 'yes' ELSE 'no' END AS flag
FROM employee;

沒有 lambda,似乎更簡單了。

其實,CASE WHEN 表達式還是相當于定義了一個函數。這還是把表達式定義的函數當成循環運算的參數,本質上仍是 lambda 語法。只是 SQL 更簡潔,已經看不出 lambda 語法的形式了。

SQL 專業面向結構化數據計算,僅支持二維數據表這一種集合,lambda 函數傳入參數只能是記錄。SQL 就不需要像 Python 那樣顯式定義一個 row 參數,而可以直接訪問字段,這會更便捷。大多數情況下,lambda 函數中可以直接使用字段名,只有存在同名字段時才需要冠以表名(或表別名)以示區分。這樣,表名和記錄參數都省了,SQL 就把 lambda 函數寫成了簡單表達式,將 lambda 語法化于無形了。

esProc SPL 繼承了 SQL 這些優點,同樣把 lambda 化于無形:

employee.derive(if(position == "manager" && salary > 5000, "yes","no"))

數據集合并不只有數據表這一種。SQL 不支持其他形式的集合,處理起來會麻煩了。對于單值成員組成的集合,SQL 還可以用只有一個字段的數據表來對付。比如求一組數值的平方和,SQL 這樣寫:

create table numbers asselect value as nfrom (select 4.3 as value union all select 2.3 union all select 6.5 union all select 44.1) t;
select sum(n*n) from numbers;

這組數值還要額外起一個字段名和表名,有點啰嗦了。

Python 支持單值組成的集合,可以用 lambda 語法寫出這樣的運算:

numbers=pd.Series([4.3,2.3,6.5,44.1])
result=numbers.apply(lambda x: x * x).sum()

SPL 也有單值集合:

numbers=[4.3,2.3,6.5,44.1]
numbers.sum(~*~)

這里,sum 函數對集合循環計算的時候,將當前成員 ~ 傳遞給 lambda 函數求平方,再由 sum 函數求和。~ 就相當于前面 Python 代碼中的 x。

在循環中,lambda 函數幾乎總是用到集合的當前成員,SPL 把這個參數固化為 ~ 符號,這樣就省去了參數的定義,從而把 lambda 寫成簡單表達式,繼續保持將 lambda 化于無形的優點。

不過,對于這種相對簡單的情況,Python 更提倡對位集合運算,可以避免使用 lambda 語法:

numbers=pd.Series([4.3,2.3,6.5,44.1])
result = (numbers * numbers).sum()

這顯得更簡潔。

前面那個員工標簽的例子也可以寫出來:

employee['flag'] = np.where((employee['position'] == 'manager') & (employee['salary'] > 5000), 'yes', 'no')

當表達式較復雜的時候,看著就不如 lamdba 語法簡潔了。而且這種寫法只適用于針對數組做過優化的運算 (比如加減乘除和這里的 if),大部分數學函數都沒有做過這種優化,碰到也只能寫成 lambda 語法。

說句題外話,這種寫法要用 where 函數,邏輯運算符是 &,而前面 lambda 語法中是用 if 函數和 and,Python 語法經常會表現出這種不一致。lambda 語法也有這種不一致問題,在 apply 函數中能用,但 sort_values 中就不能用,這些都會加大學習難度。

SPL 也支持對位集合運算的書寫形式:

(numbers ** numbers).sum()

看起來和 Python 差不多,但不如化于無形的 lambda 語法簡單了。

SPL 還支持集合的集合。實際上,只要是集合,SPL 就都可以使用化于無形的 lambda 語法。比如求員工超過 10 個的部門有哪些員工:

employee.group(department).select(~.len()>10)

group 函數按部門分組后得到一個大集合,其成員是同一部門員工組成的子集合。表達式 ~.len()>10 是一個 lambda 函數,其中的 ~ 是集合的當前成員,也就是分組子集。

select 函數對大集合循環計算時,將當前成員(子集)傳遞給 lambda 函數,判斷子集長度是否大于 10,再由 select 函數保留或舍棄這個子集。這是很自然的解題思路。

Python 一定程度也可以表示集合的集合,可以寫出類似代碼:

result=employee.groupby('department').filter(lambda x: len(x) >10)

對于集合的集合,就不能再使用對位運算了,采用 lambda 語法是 Python 最簡單的寫法,換其它方法,思路和代碼都會變得更復雜。

SQL 不能描述集合的集合,對于這個問題要換種思路去實現(麻煩很多),lamdba 語法對這個問題已經無能為力了。

SPL 不僅僅是針對結構化數據計算的,但由于結構化數據過于常見,SPL 和 SQL 一樣專門做了語法簡化。再看一下前面計算員工標簽列的例子,其實 SPL 引用字段的完整寫法應該是 ~.position、~.salary,而 SPL 也提供了直接訪問字段的便捷機制,就能把 lambda 函數寫的和 SQL 一樣簡潔:

if(position == "manager" && salary > 5000, "yes","no")

Python 沒做這種簡化,只能寫成下面這樣,會導致這種最常見的情況寫起來比較啰嗦。

lambda row: 'yes' if row['position'] == 'manager' and row['salary'] > 5000 else 'no'

除了當前成員之外,針對有序集合的循環計算經常還會用到成員的序號。比如:要取出一組數值中,第偶數個成員。簡單思路是循環計算這個集合,如果成員的序號能被 2 整除就保留,否則就舍棄。

Python 只能給 lambda 函數傳入當前成員這一個參數,必須改造這個集合,給每個成員附加上序號,才能實現這個思路:

result = filter(lambda x: x[0] % 2 == 1, enumerate(number))
even_index_members = [x[1] for x in result]

enumerate 函數將 number 的每個成員都變成數組,數組的第 0 個成員是序號,第 1 個成員是原來的數值。這樣,lambda 函數才能用 x[0] 取得成員序號。過濾后還要把原來的數值拆出來,這個過程很繞,代碼也繁瑣。

SQL 基于無序集合,成員序號沒有意義,這個問題又得繞路實現。

SPL 用 #表示當前成員的序號,用上述簡單思路寫出的代碼非常簡潔:

number.select(# % 2 ==0)

#和 ~ 一樣,也是 SPL 循環函數中 lambda 函數的傳入參數。

小結一下:

SQL 把二維數據表運算的 lambda 語法化于無形,用于描述常規結構化數據集合運算還是比較方便簡捷的,但不能支持結構化數據以外的集合。Python 支持各種形式的集合,但 lambda 函數代碼寫起來也有些啰嗦,適應面不全面,語法風格也不太一致。SPL 繼承了 SQL 的所有優勢,且對各種形式的集合都可以使用化于無形的 lambda 語法,引入了 ~、# 等符號,進一步簡化代碼,而且適應面廣且風格統一,是三者中最強的。

SPL是開源免費的,歡迎下載試用~~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/88428.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/88428.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/88428.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

day42

1. 回調函數:把一個函數當成“任務清單”交給另一個函數,等后者干完活,就按清單執行這個函數。比如點外賣后留電話,騎手送到了就打電話(執行回調)通知你。 2. lambda函數:臨時寫的超短函數&…

百度日志中臺前端重構實踐

日志中臺是百度內部針對打點數據的全生命周期管理平臺,作為公司日志數據的唯一入口,承擔以下核心職能:1.功能覆蓋:提供從數據采集、傳輸、存儲到查詢分析的一站式服務,支持產品運營分析、研發性能監控、運維管理等多元…

資訊安全 (Information Security)3大 “CIA“要素

資訊安全之3大要素,業界慣用"CIA"稱之,包括機密性 (Confidentiality)、完整性(Integrity)與可用性(Availability);更應增加諸如鑑別性、可歸責性、不可否認性與可靠性。 1.機密性 (Confidentiality) 機密性是指採用適當的安全機制…

php后臺增加權限控制

背景 最近在對接某大廠,部署差不多了,但是在漏洞掃描環節有問題,前端是用vue代碼寫的。后端是php。發現前端路由可以攔截未登錄的url。但是后端php接口不用登錄就能訪問,很危險 解決方法 一、創建 Auth 中間件 首先創建一個專門…

跨平臺后端編程ASP.NET CORE Razor新一代Web開發框架C#

asp.net core Razor動態語言編程代替asp.net .aspx更高級嗎? https://blog.csdn.net/xiaoyao961/article/details/148846065 C#Blazor應用-跨平臺WEB開發VB.NET-CSDN博客 https://blog.csdn.net/xiaoyao961/article/details/148846437 Products.razor文件,Blazor和…

Storm-Pulse 全國強對流預報接口深度解析:從技術原理到防災應用(附API接入示例)

2025年6月14日安徽省氣象臺發布的強對流黃色預警中,合肥、阜陽等地出現了小時雨量 30-50 毫米的短時強降水和8-10級雷暴大風,局地甚至觀測到云閃現象。強對流天氣是指由強烈上升氣流引發的突發性、高破壞力天氣現象,涵蓋了短時強降水、雷暴大…

2024中國科學技術大學計算機保研上機真題

中國科學技術大學計算機保研上機真題 在線測評鏈接:https://pgcode.cn/problem 運動會比賽日程安排 題目描述 某運動會設立 M M M 個比賽項目,每個運動員(共 N N N 個運動員)可以參加多個項目,每個項目的比賽時長…

(LeetCode 面試經典 150 題) 122. 買賣股票的最佳時機 II (貪心)

題目&#xff1a;122. 買賣股票的最佳時機 II 思路&#xff1a;貪心&#xff0c;時間復雜度0(n)。 當天比前一天值大&#xff0c;就進行賣出的交易。購入是默認前一天已購入。 C版本&#xff1a; class Solution { public:int maxProfit(vector<int>& prices) {int…

一篇文章了解XML

一、什么是 XML&#xff1f; XML 是一種結構化數據的標記語言&#xff0c;用來存儲、傳輸和描述數據。 它和 HTML 很像&#xff0c;但它的標簽是自定義的&#xff0c;不限定格式和外觀&#xff0c;而是強調數據的結構和含義。 XML不是用來展示數據的&#xff0c;HTML是用來展…

react經驗:i18n配置換行的富文本

應用場景 調用"useTranslations().rich"輸出換行的文本。 實施步驟 1.翻譯文件 例如:zh.json {"home":"第一行<br></br>第二行<font>加粗文本</font>" }2.調用rich處理標簽 t.rich(home, { br: () > <br /&g…

Wpf中控件作為Binding的源

1、Xaml代碼 Slider 滑動控件&#xff0c;設置了最小值0和最大值100&#xff0c;TextBox作為Binding的目標對象&#xff0c;它的Text屬性作為Binding目標的屬性&#xff0c;Binding的源的Source就是slider_test這個Slider滑動控件&#xff0c;Binding的源的Path就是slider_test…

【機器學習深度學習】典型的模型訓練過程

目錄 一、模型訓練直觀圖 二、核心目標 三、訓練過程詳解 3.1 訓練階段 1、準備起點&#xff1a;輸入數據 初始參數權重 2、模型嘗試預測&#xff1a;變換計算 (前向傳播) 3、檢查錯誤&#xff1a;計算損失值 4、學習的關鍵&#xff1a;反向傳播 梯度下降法 (調整權…

Mysql8.0版本未卸載干凈如何重新下載

Mysql8.0版本未卸載干凈如何重新下載 安裝前準備 清理現有安裝&#xff08;確保干凈環境&#xff09; :: 停止并卸載現有MySQL服務 net stop MySQL >nul 2>&1 sc delete MySQL >nul 2>&1:: 刪除舊數據目錄 rd /s /q "C:\ProgramData\MySQL" &…

垃圾收集器G1ZGC詳解

G1收集器(-XX:UseG1GC) G1 把堆劃分為許多大小相同的 Region&#xff08;默認 1~32 MB&#xff0c;一個堆通常包含上千個 Region&#xff0c;JVM目標是不超過2048個Region(JVM源碼里TARGET_REGION_NUMBER 定義)&#xff09; 不再是傳統的 Eden、Survivor、Old 靜態分代模型&…

Bootstrap 5學習教程,從入門到精通,Bootstrap 5 彈出框(Popovers) 語法知識點及案例(22)

Bootstrap 5 彈出框(Popovers) 語法知識點及案例 一、彈出框基本概念 彈出框(Popovers)是Bootstrap提供的一個小型覆蓋層組件&#xff0c;用于顯示額外的信息&#xff0c;當用戶點擊某個元素時出現&#xff0c;再次點擊時消失。 二、彈出框基本語法知識點 1. 必需屬性 dat…

輕巧靈動,智啟未來 ——Kinova Gen3 Lite 機器人輕松解鎖各行業自動化新姿勢

近年來&#xff0c;Kinova Gen3 Lite 機器人憑借其卓越的性能、靈活的應用能力以及出色的性價比&#xff0c;在全球范圍內掀起了一股熱銷狂潮。無論是科研機構、高校實驗室&#xff0c;還是工業制造企業&#xff0c;都對它青睞有加。其銷量持續攀升&#xff0c;市場占有率不斷擴…

STM32 實現PID

&#x1f9f1; 一、PID核心模塊&#xff08;模塊化設計&#xff09; 頭文件 pid_controller.h #pragma once #include <stdint.h>typedef struct {// 可調參數float Kp, Ki, Kd; // PID系數float output_min; // 輸出下限float output_max; // 輸出上…

基于MATLAB的BP神經網絡回歸模型在空氣質量預測中的應用

說明&#xff1a;這是一個機器學習實戰項目&#xff08;附帶數據代碼文檔&#xff09;&#xff0c;如需數據代碼文檔可以直接到文章最后關注獲取。 1.項目背景 隨著城市化進程的加快和工業化的不斷發展&#xff0c;空氣質量問題日益受到廣泛關注。空氣中污染物如PM2.5、PM10、…

Linux docker拉取鏡像報錯解決

1、錯誤提示&#xff1a; Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection 主要原因就是docker源不正確&#xff0c;需要配置一下。 2、報錯如下&#xff1a; 3、解決辦法&#x…

stm32week17+18+19+20

stm32學習 十二.串口 5.USART的HAL庫用法 USART/UART異步通信配置步驟&#xff1a; 配置串口工作參數&#xff1a;HAL_UART_Init();串口底層初始化&#xff1a;HAL_UART_MspInit();開啟串口異步接收中斷&#xff1a;HAL_UART_Receive_IT();設置優先級&#xff0c;使能中斷&…