深入探討 List Module 所提供的 Function (G ~ P)

栏目: ASP.NET · 发布时间: 7年前

内容简介:F# 的 List module 提供眾多本文探討英文字母 G ~ P 開頭的 function。macOS High Sierra 10.13.3

F# 的 List module 提供眾多 List 常用的 Higher Order Function,要能發揮 FP 的威力,首先必須能活用內建 function。

本文探討英文字母 G ~ P 開頭的 function。

Version

macOS High Sierra 10.13.3

.NET Core SDK 2.1.101

JetBrains Rider 2017.3.1

F# 4.1

List.head

傳回 list 第一個 element,相當於 list 的 Head property

list : 'T list -> 'T

[ 1; 2; 3 ]
|> List.head
|> printf "%d"
// 1

List.indexed

將 element 的 key 與 value 封裝成 tuple,以 list 回傳

list : 'T list -> (int * 'T) list

[ 1; 2; 3 ]
|> List.indexed
|> printf "%A"
// [(0, 1); (1, 2); (2, 3)]

List.init

根據 index 值建立新的 list

int -> initializer : (int -> 'T) -> 'T list

List.init 10 (fun idx -> idx * 2)
|> printf "%A"
// [0; 2; 4; 6; 8; 10; 12; 14; 16; 18]

List.isEmpty

判斷 list 是否為空,相當於 list 的 IsEmpty property

list : 'T list -> bool

[]
|> List.isEmpty
|> printf "%b"
// true

List.item

傳回指定 index 的 element 值,相當於 list 的 Item property

index : int -> list : 'T list -> 'T

[ 1; 2; 3 ]
|> List.item 2
|> printf "%d"
// 3

List.iter

對每個 element 執行回傳值為 unit 的 action function

action : ('T -> unit) -> list : 'T list -> unit

[ 1; 2; 3 ]
|> List.iter (printf "%A ")
// 1 2 3

List.iter2

同時對兩個 list 的每個 element 執行回傳值為 unit 的 action function

action : ('T1 -> 'T2 -> unit) -> list1 : 'T1 list -> list2 : 'T2 list -> unit

let list1 = [ 1; 2; 3 ]
let list2 = [ 4; 5; 6 ]

let action elm1 elm2 =
    printf "%d " (elm1 + elm2) 

List.iter2 action list1 list2
// 5 7 9

List.iteri

對每個 element 執行回傳值為 unit 的 action function,但會將 index 也傳入 action function

action : (int -> 'T -> unit) -> list : 'T list -> unit

[ 1 .. 3 ]
|> List.iteri (fun idx elm -> printfn "%d : %d" idx elm)
// 0 : 1
// 1 : 2
// 2 : 3

List.iteri2

同時對兩個 list 的每個 element 執行回傳值為 unit 的 action function,但會將 index 也傳入 action function

action : (int -> 'T1 -> 'T2 -> unit) -> list1 : 'T1 list -> list2 : 'T2 list -> unit

let list1 = [ 1; 2; 3 ]
let list2 = [ 4; 5; 6 ]

let action idx elm1 elm2 =
    printfn "%d : %d" idx (elm1 + elm2) 

List.iteri2 action list1 list2
// 0 : 5
// 1 : 7
// 2 : 9

List.last

傳回 list 最後一個 element

list : 'T list -> 'T

[ 1; 2; 3 ]
|> List.last
|> printf "%d"
// 3

List.length

傳回 list 的 element 個數,相當於 list 的 Length property

list: 'T list -> int

[ 1; 2; 3 ]
|> List.length
|> printf "%d"
// 3

List.map

將 list 的每個 element 根據 mapping function 轉換成另外一個 value 的 list

mapping : ('T -> 'U) -> list : 'T list -> 'U list

[ 1; 2; 3 ]
|> List.map (fun elm -> elm * elm)
|> printf "%A"
// [1; 4; 9]

若經過 mapping function 後 element 個數不一樣,請用 List.collect()

List.map2

將兩個 list 的每個 element 根據 mapping function 轉換成另外一個 value 的 list

mapping : ('T1 -> 'T2 -> 'U) -> list1 : 'T1 list -> list2 : 'T2 list -> 'U list

let list1 = [ 1; 2; 3 ]
let list2 = [ 4; 5; 6 ]

List.map2 (fun elem1 elem2 -> elem1 + elem2) list1 list2
|> printf "%A"
// [5; 7; 9]

List.map3

將三個 list 的每個 element 根據 mapping function 轉換成另外一個 value 的 list

mapping : ('T1 -> 'T2 -> 'T3 -> 'U) -> list1 : 'T1 list -> list2 : 'T2 list -> list3 : 'T3 list -> 'U list

let list1 = [ 1; 2; 3 ]
let list2 = [ 4; 5; 6 ]
let list3 = [ 7; 8; 9 ]

List.map3 (fun elm1 elm2 elm3 -> elm1 + elm2 + elm3) list1 list2 list3
|> printf "%A"
// [12; 15; 18]

List.mapFold

相當於 List.map() + List.fold() 合體,回傳為 tuple。

mapping : ('State -> 'T -> 'Result * 'State) -> state : 'State -> list : 'T list -> 'Result list * 'State

[ 1; 2; 3 ]
|> List.mapFold (fun acc elm -> (elm * elm , acc + elm * elm)) 0
|> printf "%A"
// ([1; 4; 9], 14)

mapping funciton 中,回傳的是 tuple。

  • 第 1 個 element 為 List.map() 的結果
  • 第 2 個 element 為 List.fold() 的結果

List.mapFoldBack

相當於 List.map() + List.fold() 合體,回傳為 tuple,但從 list 的尾部開始,signature 的順序也不一樣

mapping : ('T -> 'State -> 'Result * 'State) -> list : 'T list -> state : 'State -> 'Result * 'State

let list1 = [ 1; 2; 3 ]

List.mapFoldBack (fun elm acc -> (elm * elm , acc + elm * elm)) list1 0
|> printf "%A"
// ([1; 4; 9], 14)

List.mapi

對 list 的每個 element 根據 mapping function 轉換成另外一個 value 的 list,但會將 index 也傳入 mapping function

mapping : (int -> 'T -> 'U) -> list : 'T list -> 'U list

[ 1; 2; 3 ]
|> List.mapi (fun idx elm -> idx * elm)
|> printf "%A"
// [0; 2; 6]

List.mapi2

同時對兩個 list 的每個 element 根據 mapping function 轉換成另外一個 value 的 list,但會將 index 也傳入 mapping function

let list1 = [ 1; 2; 3 ]
let list2 = [ 4; 5; 6 ]

let mapping idx elm1 elm2 =
    idx + elm1 + elm2

List.mapi2 mapping list1 list2
|> printf "%A"
// [5; 8; 11]

List.max

傳回 list 內最大的值

list : 'T list -> 'T

[ 1; 2; 3 ]
|> List.max
|> printf "%d"
// 3

List.maxBy

傳回 list 內的最大值,但所比較的是經過 projection function 轉換過的值

project : ('T -> 'U) -> list : 'T list -> 'T

[ 1; 2; 3 ]
|> List.maxBy (fun elm -> 1 - elm)
|> printf "%d"
// 1

[1; 2; 3] 經過 projection function 後為 [0; -1; -2] ,所以最大值為 0 ,但 List.maxBy() 回傳的是原 list 的值,所以為 1

Projection function 的值只是比較用,不是回傳用

List.min

傳回 list 內最小的值

list : 'T list -> 'T

[ 1; 2; 3 ]
|> List.min
|> printf "%d"
// 1

List.minBy

傳回 list 內的最小值,但所比較的是經過 projection function 轉換過的值

project : ('T -> 'U) -> list : 'T list -> 'T

[ 1; 2; 3 ]
|> List.minBy (fun elm -> 1 - elm)
|> printf "%d"
// 3

[1; 2; 3] 經過 projection function 後為 [0; -1; -2] ,所以最小值為 0 ,但 List.minBy() 回傳的是原 list 的值,所以為 3

Projection function 的值只是比較用,不是回傳用

List.ofArray

由 array 轉成 list

array : 'T [] -> 'T list

[| 1; 2; 3 |]
|> List.ofArray
|> printf "%A"
// [1; 2; 3]

List.ofSeq

由 sequence 轉成 list

source : seq<'T> -> 'T list

seq { 1 .. 5 }
|> List.ofSeq
|> printf "%A"
// [1; 2; 3; 4; 5]

List.pairWise

根據 list 順序,回傳兩兩成為 tuple 的 list

list : 'T list -> ('T * 'T) list

[ 1; 2; 3; 4 ]
|> List.pairwise
|> printf "%A"
//[(1, 2); (2, 3); (3, 4)]

List.partition

將 list 根據 predicate function 拆成兩個 list,同時放在一個 tuple 中傳回

predicate : ('T -> bool) -> list : 'T list -> 'T list * 'T list

[ 1 .. 10 ]
|> List.partition (fun elm -> elm % 2 = 0)
|> printf "%A"
// ([2; 4; 6; 8; 10], [1; 3; 5; 7; 9])

List.permute

List 重新根據 indexMap function 的規則,重新調整 element 順序

indexMap : (int -> int) -> list : 'T list -> 'T list

[ 1; 2; 3 ]
|> List.permute (fun idx -> (idx + 1) % 3)
|> printf "%A"
// [3; 1; 2]

List.pick

找出符合 chooser function 條件的第一個 element

chooser : ('T -> 'U option) -> list : 'T list -> -> 'U

let chooser elm = 
    match elm with 
    | elm when elm % 2 = 0 -> Some elm
    | _ -> None

[ 1; 2; 3 ]
|> List.pick chooser
|> printf "%A"
// 2

若找不到 element,會拋出 KeyNotFoundException : An index satisfying the predicate was not found in the collection.

Q: List.find()List.pick() 有何差異?

相同

  • 都用來找資料

  • 找不到資料都會拋出 KeyNotFoundException

相異

  • List.find() 的 predicate function 為 'T -> bool
  • List.pick() 的 chooser function 為 'T -> 'U option

若 fuction 回傳為 option ,則適合用 List.pick() ,否則使用 List.find()

Conclusion

  • List module 所提供的 function 都必須非常熟練,因為這些都是常用的 Higher Order Function,算是 FP 的基本功

Reference

MSDN , Collection.List Module (F#)


以上所述就是小编给大家介绍的《深入探討 List Module 所提供的 Function (G ~ P)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Algorithm Design Manual

The Algorithm Design Manual

Steven S Skiena / Springer / 2011-11-14 / GBP 55.07

....The most comprehensive guide to designing practical and efficient algorithms.... Written by a well-known algorithms researcher who received the IEEE Computer Science and Engineering Teaching Aw......一起来看看 《The Algorithm Design Manual》 这本书的介绍吧!

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具