https://github.com/juliaaplavin/fleximaps.jl
Generalize `map`: make it lazy, filtering, flattening, ...
https://github.com/juliaaplavin/fleximaps.jl
data-manipulation filtering lazy mappings
Last synced: 6 months ago
JSON representation
Generalize `map`: make it lazy, filtering, flattening, ...
- Host: GitHub
- URL: https://github.com/juliaaplavin/fleximaps.jl
- Owner: JuliaAPlavin
- License: mit
- Created: 2024-02-18T17:57:19.000Z (over 2 years ago)
- Default Branch: master
- Last Pushed: 2024-12-16T16:14:56.000Z (over 1 year ago)
- Last Synced: 2025-01-20T06:45:51.729Z (over 1 year ago)
- Topics: data-manipulation, filtering, lazy, mappings
- Language: Julia
- Homepage:
- Size: 65.4 KB
- Stars: 14
- Watchers: 2
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# FlexiMaps.jl
All-familiar `map` on steroids: a set of functions that generalize `map`.
## `filtermap`
`filtermap(f, X)`: map and filter a collection in one go.
Most useful when the mapped function shares some computations with the filter predicate.
Returns same as `map(f, X)`, dropping elements where `f(x)` is `nothing`.
Return `Some(nothing)` from `f` to keep `nothing` in the result.
```julia
filtermap(x -> x % 3 == 0 ? x^2 : nothing, 1:10) == [9, 36, 81]
```
_Analogous to `filter_map` in Rust_
## `flatmap`/`flatten`
These functions are similar to `Iterators.flatmap` and `Iterators.flatten`, but operate on arrays in a more performant and generic manner.
`flatmap(f, X)`: apply `f` to all elements of `X` and flatten the result by concatenating all `f(x)` collections.
`flatmap(fₒᵤₜ, fᵢₙ, X)`: apply `fₒᵤₜ` to all elements of `X`, and apply `fᵢₙ` to the results. Basically, `[fᵢₙ(x, y) for x in X for y in fₒᵤₜ(x)]`.
`flatmap(f, X)` is similar to `mapreduce(f, vcat, X)` and `SplitApplyCombine.mapmany(f, A)`, but more efficient and generic.
Defining differences include:
- better result type inference
- keeps array types, eg `StructArray`
- works with empty collections
- supports arbitrary iterators, not only arrays
_Analogous to `flat_map` in Rust, and `SelectMany` in C#_
`flatten(X)`: flatten a collection of collections by concatenating all elements, equivalent to `flatmap(identity, X)`.
## `mapview` (lazy `map`)
`mapview(f, X)`:
- like `map(f, X)`, but works lazily, doesn't materialize the result returning a view instead.
- like `Iterators.map(f, X)`, but with better collection support, type stability, etc.
Works on different collections and arbitrary iterables. Collection types are preserved when possible for ranges, arrays, dictionaires. Passes `length`, `keys` and others directly to the parent. Does its best to determine the resulting `eltype` without evaluating `f`. Supports both getting and setting values (through `Accessors.jl`).
```julia
X = [1, 2, 3]
mapview(x -> x + 1, X) == [2, 3, 4] # a view of X, doesn't take extra memory
X = Dict(:a => 1, :b => 2, :c => 3)
mapview(x -> x + 1, X) == Dict(:a => 2, :b => 3, :c => 4) # same with Dict
X = [1, 2, 3]
mapview(x -> x + 1, (x for x in X)) # and with iterator
```
```julia
julia> X = [1, 2, 3.]
julia> Y = mapview(exp10, X)
3-element FlexiMaps.MappedArray{Float64, 1, typeof(exp10), Vector{Float64}}:
10.0
100.0
1000.0
# setindex! works for all functions/optics supported by Accessors
julia> Y[2] = 10^10
# when invertible, push! also works
julia> push!(Y, 10000)
julia> X
4-element Vector{Float64}:
1.0
10.0
3.0
4.0
```
# `maprange`
`maprange(f, start, stop; length)`: `length` values between `start` and `stop`, so that `f(x)` is incremented in uniform steps. Uses `mapview` in order not to materialize the array.
`maprange(identity, ...)` is equivalent to `range(...)`. Most common application - log-spaced ranges:
`maprange(log, 10, 1000, length=5) ≈ [10, 31.6227766, 100, 316.227766, 1000]`
Other transformations can also be useful:
`maprange(sqrt, 16, 1024, length=5) == [16, 121, 324, 625, 1024]`