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 # assert equal $not_found null
# ``` # ```
export def "iter find" [ # -> any | 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 { try {
$list | filter $predicate | get 0? filter $fn | get 0?
} catch { } catch {
null null
} }
@ -51,21 +50,12 @@ export def "iter find" [ # -> any | null
export def "iter intersperse" [ # -> list<any> export def "iter intersperse" [ # -> list<any>
separator: any, # the separator to be used separator: any, # the separator to be used
] { ] {
let list = (self collect) reduce -f [] {|it, acc|
$acc ++ [$it, $separator]
let len = ($list | length); }
if ($list | is-empty) { | match $in {
return $list [] => [],
} $xs => ($xs | take (($xs | length) - 1 ))
$list
| enumerate
| reduce -f [] {|it, acc|
if ($it.index == $len - 1) {
$acc ++ [$it.item]
} else {
$acc ++ [$it.item, $separator]
}
} }
} }
@ -90,24 +80,42 @@ export def "iter intersperse" [ # -> list<any>
# ``` # ```
export def "iter scan" [ # -> list<any> export def "iter scan" [ # -> list<any>
init: any # initial value to seed the initial state 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 --noinit(-n) # remove the initial value from the result
] { ] {
let res = (reduce -f [$init] {|it, acc| reduce -f [$init] {|it, acc|
$acc ++ [(do $f ($acc | last) $it)] $acc ++ [(do $fn ($acc | last) $it)]
}) }
| if $noinit {
if $noinit { $in | skip
$res | skip
} else { } else {
$res $in
} }
} }
# Accepts inputs from a pipeline and builds a list for the `iter *` # Returns a list of values for which the supplied closure does not
# commands to work with # return `null` or an error. It is equivalent to
def "self collect" [] { # -> list<any> # `$in | each $fn | filter $fn`
reduce -f [] {|it, acc| #
$acc ++ $it # # 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) let scanned = ([a b c d] | iter scan "" {|x, y| [$x, $y] | str join} -n)
assert equal $scanned ["a" "ab" "abc" "abcd"] 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]
}