12 3 2 篩選和對映

2021-06-01 20:08:57 字數 2804 閱讀 4296

12.3.2 篩選和對映

篩選和對映是兩個最常用的序列處理運算子。在第 6 章,我們用它們處理過 f# 的函式式列表,和在 c# 中的泛型 .net list型別。linq 庫的 where 和 select 擴充套件方法已經可以處理序列,在 f# 中,我們可以使用兩個來自 seq 模組 (即 seq.map 和 seq.filter)的函式來達到相同的效果。

使用高階函式

使用 f# 中的 seq 模組與處理 list 相同,我們已經看到過,如何在 c# 中使用 linq 擴充套件方法。使用列表和序列,有乙個顯著區別:序列是延遲的。處理的**直到我們從返回序列中取元素時才執行,即使在當時它只做需要的工作,為了返回使用的結果,也是一樣。我們用簡單的**段來演示一下:

var nums1 =

nums.where(n => n%3 == 0)

.select(n => n * n)

let nums1 =

nums |> seq.filter (fun n -> n%3=0)

|> seq.map (fun n -> n * n)

當我們執行這段**時,它不會處理任何元素;它只建立乙個物件,表示這個序列,可以用於訪問元素。這也意味著:值 nums 可以是無窮的數字序列。如果我們只訪問序列的前 10 元素,**將正常工作,因為篩選和對映都是延遲處理資料的。

你可能已經熟悉使用高階處理函式,當我們在第 6 章中廣泛討論之後,在整本書中,提供了很多的例子。在本章中,我們將轉而討論一下表達替代工作流的其他方法。

使用查詢和序列表示式

在 c# 3.0 中,我們可以使用新的查詢表示式語法,來寫有關對映和篩選資料的操作。查詢表示式支援許多其他運算子,但我們會只關注對映和篩選,以顯示函式技術和 f# 功能。

雖然 f# 沒有提供專門的查詢表示式的支援,仍可以輕鬆地寫對映和篩選資料的查詢,使用序列表示式。這是由於序列表示式可以在 f# 中任意位置使用,而不是僅僅作為返回序列的函式實現。清單 12.9 顯示了我們我們前面的示例,如何使用 c# 中的查詢和 f# 中的序列表示式來實現的。

listing 12.9 filtering and projecting sequences in c# and f#

c#f#

var nums1 =

from n in nums

where n%3 == 0

select n * n;

let nums1 = seq

在 c# 中,查詢表示式和迭代器是完全不同的,但 f# 中的序列表示式顯示它們從概念上講如何相關。查詢表示式中的每個部分在 f# 中都有等效結構,但它總是更加一般:from 子句是由簡單的 for 迴圈取代,where 子句由 if 條件取代,select 子句與 yield 語句相對應,對映表示為乙個通常的計算。

c# 查詢表示式語法還支援一些其他的運算子,用 f# 序列表示式不容易表達。這意味著,c# 版本功能更強大,但 f# 實現更加統一。

要注意 c# 查詢表示式和 f# 序列表示式內部是如何工作。c# 查詢表示式以明確的方式轉化成一系列呼叫,比如:where、select、selectmany、join 和 groupby,使用 lambda 表示式。這些通常是擴充套件方法,但不一定,編譯器不關心查詢表示式的意思,只要翻譯的**是有效的就行。這個「資料來源不可知論(data source agnosticism)"對於資料處理技術至關重要,比如 linq to objects,和 linq to sql,我們不久將使用它,來展示查詢語法如何能用於處理其它種類的值。

另一方面,序列表示式可以用來表達更加複雜和通用的結構。我們可以複製 yield 結構,把來自資料來源的乙個專案返回為兩個元素。這使用 c# 中的迭代器可以很容易實現,但是,使用查詢語法,不可能表達"內聯"轉換。

linq 中的其他查詢運算子

在 c# 3.0 中,查詢表示式語法是專為從各種資料來源檢索和格式化資料的,因此,它包括的操作不止對映和篩選。這些操作符主要就為此目的,在 f# 中並沒有專門的對應語法。所有這些標準運算子可以作為常規的高階函式,來操作序列。例如,排序資料:

var q =

from c in customers

orderby c.name

select c;

let q =

customers

|> seq.sortby (fun c -> c.city)

作為給 seq.sortby 運算子的第乙個引數的函式,指定在比較兩個元素時,應該處理元素的哪個屬性。在 c# 的查詢語法中,這對應於跟在  orderby 子句後的表示式。c# 編譯器使用 lambda 函式,將此表示式轉換為對標準orderby 方法的呼叫。f# 中作為高階函式使用的另乙個操作是分組:

var q =

from c in customers

group c by c.city;

let q =

customers

|> seq.groupby (fun c -> c.city)

要地一上序列分組,需要指定乙個函式返回鍵值,表示乙個元素所屬的組。c# 再次有專門的語法,但在 f# 的**段中,我們使用標準的 lambda 函式。

在這些示例中,兩個版本的**看起來是合理的。然而,當我們需要寫 f# 的**,一些操作需要把對映和篩選混到一起,只能使用高階函式來寫,那麼,等效的 c# 查詢表示式會更容易理解。

在 f# 編譯器中,序列表示式的實現進行了優化,但是,如果沒有這些優化,它可能與 c# 查詢表示式一樣執行。任意乙個序列表示式,可以轉化為乙個標準的函式呼叫序列。類似於 c#,我們可以提供這些函式的自定義實現,這樣,可以更深入理解在 f# 中轉換是如何工作的。f# 語言使用數量很少的操作,嚴重依賴於單個操作,被稱為平面對映(flattening projection)。

pandas進行條件篩選和組合篩選

對pandas中的dataframe進行條件篩選,即篩選出符合條件的資料條 df pd.dataframe a b c 0 100 a 1 1 200 b 2 2 300 c 3 3 400 d 4 4 500 e 5 1 找出df中a列值為100的所有資料 也可以是小於 大於 小於等於 大於等於 ...

建立流的5種方式 篩選 對映 排序

一 建立流的5種方式 建立流的5種方式 public static void test1 二 篩選與切片 篩選與切片 filter 接收lambda,從流中排除某些元素 limit 截斷流,使袁術不超過給定的數量。skip n 跳過元素,返回乙個扔掉了前n個元素的流。若元素中不足n個,則返回乙個空流...

pandas條件組合篩選和按範圍篩選

1 從記錄中選出所有fault code列的值在fault list 487,479,500,505 這個範圍內的記錄 要用.isin 而不能用in,用 in以後選出來的值都是true 和false,然後報錯 valueerror the truth value of a series is amb...