Common functions
Functions available in multiple modules, each version customized for its target type
Operations: access, construct, find, select, aggregate...
☝️ Convention used here:
Functions are given by their name
To use them, we need to qualify them by the module.
The last parameter is omitted for brevity
It's always the collection.
Example: head
vs List.head x
Access to an element
By index
x[index]
By index
item index
tryItem index
First element
head
tryHead
Last element
last
tryLast
💣 ArgumentException
or IndexOutOfRangeException
Cost ⚠️
head
O(1)
O(1)
O(1)
item
O(1)
O(n) ❗
O(n) ❗
last
O(1)
O(n) ❗
O(n) ❗
length
O(1)
O(n) ❗
O(n) ❗
Combine collections
append
/ @
2 collections of sizes N1 et N2
N1 + N2
concat
K collections of sizes N1..Nk
N1 + N2 + ... + Nk
zip
2 collections of same size N ❗
N pairs
allPairs
2 collections of sizes N1 et N2
N1 * N2 pairs
Find an element
Using a predicate f : 'T -> bool
:
First found
find
tryFind
Last found
findBack
tryFindBack
Index of first found
findIndex
tryFindIndex
Index of last found
findIndexBack
tryFindIndexBack
Search elements
By value
At least 1
contains value
By predicate f
At least 1
exists f
"
All
forall f
Select elements
All those found
filter f
First ignored
skip n
skipWhile f
First found
take n
takeWhile f
truncate n
☝ Notes:
skip
,take
vstruncate
whenn
> collection's sizeskip
,take
: 💣 exceptiontruncate
: empty collections w/o exception
Alternative for
Array
: Rangearr[2..5]
Map elements
Functions taking as input:
A mapping function
f
(a.k.a. mapper)A collection of type
~~~~ 'T
with~~~~
meaningArray
,List
, orSeq
map
'T -> 'U
'U ~~~~
As many in than out
mapi
int -> 'T -> 'U
'U ~~~~
As many in than out
collect
'T -> 'U ~~~~
'U ~~~~
flatMap
choose
'T -> 'U option
'U ~~~~
Less
pick
'T -> 'U option
'U
1 (the first matching) or 💣
tryPick
'T -> 'U option
'U option
1 (the first matching)
map
vs mapi
map
vs mapi
mapi
≡ map
with index
The difference is on the f
mapping parameter:
map
:'T -> 'U
mapi
:int -> 'T -> 'U
→ the additionalint
parameter is the item index
Alternative to mapi
mapi
Apart from map
and iter
, no xxx
function has a xxxi
variant.
💡 Use indexed
to obtain elements with their index
map
vs iter
map
vs iter
iter
looks like map
with
no mapping:
'T -> unit
vs'T -> 'U
no output:
unit
vs'U list
But iter
is used for a different use case:
→ to trigger an action, a side-effect, for each item
Example: print the item to the console
choose
, pick
, tryPick
choose
, pick
, tryPick
Signatures:
• choose : mapper: ('T -> 'U option) -> items: 'T ~~~~ -> 'U ~~~~
• pick : mapper: ('T -> 'U option) -> items: 'T ~~~~ -> 'U
• tryPick : mapper: ('T -> 'U option) -> items: 'T ~~~~ -> 'U option
Notes:
The mapper may return
None
for some items not mappable (or just ignored)~~~~
stands for the collection type:Array
,List
, orSeq
Different use cases:
choose
to get all the mappable items mappedpick
ortryPick
to get the first one
When no items are mappable:
choose
returns an empty collectiontryPick
returnsNone
pick
raises aKeyNotFoundException
💣
Examples:
Analogies:
choose f
≃
• collect (f >> Option.to{Collection})
• (filter (f >> Option.isSome)) >> (map (f >> Option.value))
(try)pick f
≃
• (try)find(f >> Option.isSome)) >> f
• choose f >> (try)head
Aggregate
Specialized aggregate functions
×
countBy
×
max
maxBy
comparison
min
minBy
comparison
sum
sumBy
📍
average
averageBy
📍
CountBy
Uses a projection f: 'T -> 'U
to compute a "key" for each item
Returns all the keys with the number of items having this key
💡 Useful to determine duplicates:
Max(By), Min(By)
☝️ Notes:
Unions are
IComparable
by default →N
follows thecomparison
constraint.maxBy
andminBy
perform no mapping: → See the returned value in the example:Two
(N
), ≠"Two"
(string
)
Sum(By), Average(By)
☝️ Notes:
The error
FS0001
at line 1 reveals the Monoid constraint (see below) that must be satisfied by:The item type
'T
forsum
andaverage
,The projection return type
'U
forsumBy
andaverageBy
.
sumBy
andaverageBy
perform a mapping → See the returned type in the example:int
≠ item type:int * string
sum
≡sumBy id
average
≡averageBy id
Monoid constraint
To satisfy the monoid constraint, a type must have:
A
Zero
static read-only propertyAn overload of the
+
operator
Example of a custom type with these members:
Versatile aggregate functions
• fold (f: 'U -> 'T -> 'U) (seed: 'U) items
• foldBack (f: 'T -> 'U -> 'U) items (seed: 'U)
• reduce (f: 'T -> 'T -> 'T) items
• reduceBack (f: 'T -> 'T -> 'T) items
f
takes 2 parameters: an "accumulator" acc
and the current element x
→ For foldBack
, the parameters are in a reversed order: x acc
xxxBack
vs xxx
:
Iterates from last to first element
Parameters
seed
anditems
reversed (forfoldBack
)
reduce(Back)
vs fold(Back)
:
reduce(Back)
uses the first item as the seed and performs no mapping (see'T -> 'T
vs'T -> 'U
)reduce(Back)
fails if the collection is empty 💣
Examples:
Fold(Back) versatility
We could write almost all functions with fold
or foldBack
(performance aside)
Change the order of elements
Inversion
rev list
×
Sort asc
sort list
sortBy f list
Sort desc
sortDescending list
sortDescendingBy f list
Sort custom
sortWith comparer list
×
Separate
💡 Elements are divided into groups
[1..10]
[ 1 2 3 4 5 6 7 8 9 10 ]
length = 10
chunkBySize 3
[[1 2 3] [4 5 6] [7 8 9] [10]]
forall: length <= 3
splitInto 3
[[1 2 3 4] [5 6 7] [8 9 10]]
length <= 3
splitAt 3
([1 2 3],[4 5 6 7 8 9 10])
Tuple ❗
☝️ Notice how splitInto n
distributes the items equally, from left to right:
Group items
By size
💡 Items can be duplicated into different groups
[1..5]
[ 1 2 3 4 5 ]
pairwise
[(1,2) (2,3) (3,4) (4,5)]
Tuple ❗
windowed 2
[[1 2] [2 3] [3 4] [4 5]]
Array of arrays of 2 items
windowed 3
[[1 2 3] [2 3 4] [3 4 5]]
Array of arrays of 3 items
By criteria
partition
predicate: 'T -> bool
('T list * 'T list)
→ 1 pair ([OKs], [KOs])
groupBy
projection: 'T -> 'K
('K * 'T list) list
→ N tuples [(key, [related items])]
Change collection type
Your choice: Dest.ofSource
or Source.toDest
From \ to
Array
List
Seq
Array
×
List.ofArray
Seq.ofArray
×
Array.toList
Array.toSeq
List
Array.ofList
×
Seq.ofList
List.toArray
×
List.toSeq
Seq
Array.ofSeq
List.ofSeq
×
Seq.toArray
Seq.toList
×
Functions vs comprehension
The functions of List
/Array
/Seq
can often be replaced by a comprehension, more versatile:
Additional resources
Documentation FSharp.Core 👍
Last updated
Was this helpful?