add filter-map command to std iter (#8926)

# Description
as title says
This commit is contained in:
mike 2023-04-19 20:09:10 +03:00 committed by GitHub
parent 1855dfb656
commit ed64a44b82
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 50 additions and 31 deletions

View file

@ -28,11 +28,10 @@
# assert equal $not_found null
# ```
export def "iter find" [ # -> any | null
predicate: closure # the closure used to perform the search
fn: closure # the closure used to perform the search
] {
let list = (self collect)
try {
$list | filter $predicate | get 0?
filter $fn | get 0?
} catch {
null
}
@ -51,21 +50,12 @@ export def "iter find" [ # -> any | null
export def "iter intersperse" [ # -> list<any>
separator: any, # the separator to be used
] {
let list = (self collect)
let len = ($list | length);
if ($list | is-empty) {
return $list
}
$list
| enumerate
| reduce -f [] {|it, acc|
if ($it.index == $len - 1) {
$acc ++ [$it.item]
} else {
$acc ++ [$it.item, $separator]
}
reduce -f [] {|it, acc|
$acc ++ [$it, $separator]
}
| match $in {
[] => [],
$xs => ($xs | take (($xs | length) - 1 ))
}
}
@ -90,24 +80,42 @@ export def "iter intersperse" [ # -> list<any>
# ```
export def "iter scan" [ # -> list<any>
init: any # initial value to seed the initial state
f: closure # the closure to perform the scan
fn: closure # the closure to perform the scan
--noinit(-n) # remove the initial value from the result
] {
let res = (reduce -f [$init] {|it, acc|
$acc ++ [(do $f ($acc | last) $it)]
})
if $noinit {
$res | skip
reduce -f [$init] {|it, acc|
$acc ++ [(do $fn ($acc | last) $it)]
}
| if $noinit {
$in | skip
} else {
$res
$in
}
}
# Accepts inputs from a pipeline and builds a list for the `iter *`
# commands to work with
def "self collect" [] { # -> list<any>
reduce -f [] {|it, acc|
$acc ++ $it
# Returns a list of values for which the supplied closure does not
# return `null` or an error. It is equivalent to
# `$in | each $fn | filter $fn`
#
# # Example
# ```nu
# use std ["assert equal" "iter filter-map"]
#
# let res = ([2 5 "4" 7] | iter filter-map {|it| $it ** 2})
#
# assert equal $res [4 25 49]
# ```
export def "iter filter-map" [ # -> list<any>
fn: closure # the closure to apply to the input
] {
each {|$it|
try {
do $fn $it
} catch {
null
}
}
| filter {|it|
$it != null
}
}

View file

@ -48,3 +48,14 @@ export def test_iter_scan [] {
let scanned = ([a b c d] | iter scan "" {|x, y| [$x, $y] | str join} -n)
assert equal $scanned ["a" "ab" "abc" "abcd"]
}
export def test_iter_filter_map [] {
let res = ([2 5 "4" 7] | iter filter-map {|it| $it ** 2})
assert equal $res [4 25 49]
let res = (
["3" "42" "69" "n" "x" ""]
| iter filter-map {|it| $it | into int}
)
assert equal $res [3 42 69]
}