Skip to content

Commit

Permalink
add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
vituri committed May 11, 2024
1 parent 91bde74 commit 292c513
Show file tree
Hide file tree
Showing 9 changed files with 337 additions and 70 deletions.
2 changes: 2 additions & 0 deletions docs/src/adverbs.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Adverbs are functions that modify the behaviour of a function.

## API

```@docs
compose
compose_n
Expand Down
68 changes: 41 additions & 27 deletions docs/src/apply.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ We will cover some common cases below.

Given a collection `x` and a one-variable function `f`, we can apply `f` to each element of `x` as follows:

```@example 1
```@example apply
using TidierIteration;
x = [3:6;];
Expand All @@ -24,22 +24,22 @@ apply(x, f)
```

This, of course, is the same as
```@example 1
```@example apply
map(f, x)
```

or
```@example 1
```@example apply
f.(x)
```

Things get more interesting when we have a dictionary as follows:

```@example 1
```@example apply
d = Dict(i => i for i in [1:4;])
```

```@example 1
```@example apply
apply(d, f)
```

Expand All @@ -49,32 +49,26 @@ We can see a dictionary as a collection with named entries, and `apply(d, f)` me

In case you want to modify the keys of a dictionary, there is the special function

```@example 1
```@example apply
apply_keys(d, x -> -x)
```

If you just want to apply `f` for its side-effects and return nothing, use
```@example 1
```@example apply
walk(x, f)
```

Every member of the apply family has a optional named argument `T` which is a function that will be applied to each element, usually to convert it to a specific type:
In case you want to convert each output of `f` to a specific type, you can always pass a compose function:

```@example 1
apply(x, f, T = string)
```

This is the same as

```@example 1
```@example apply
apply(x, string ∘ f)
```

## Two variables, two collections

We can apply a two-variable function `f` to two collections `x` and `y` by applying `f` to each pair `(x_i, y_i)` where `x_i` is the `i-th` element of `x` and `y_i` the `i-th` element of `y`. If `x` and `y` have different sizes, we iterate until one of them ends.

```@example 2
```@example apply2
using TidierIteration;
x = [1:4;]
Expand All @@ -86,8 +80,7 @@ apply2(x, y, f)

When `x` and `y` are dictionaries, we iterate on the set of common keys:

```@example 2
using TidierIteration;
```@example apply2
d1 = Dict(i => i for i in [1:4;])
d2 = Dict(i => i^2 for i in [3:9;])
Expand All @@ -99,7 +92,7 @@ apply2(d1, d2, f)

In this case, we can use the index of each element of `x` as the first variable to be applied on `f`, that is, we apply `f` on the pairs `(i, x_i)` for each index `i` of `x`. It is important to note that `i` is the first argument to be passed to `f`.

```@example 3
```@example iapply
using TidierIteration;
x = [3:6;]
Expand All @@ -109,7 +102,7 @@ iapply(x, f)

When `x` is a dictionary, the elements `i` are the keys of `x`:

```@example 3
```@example iapply
d = Dict(i => i for i in [1:4;])
g(k, v) = k + v
Expand All @@ -120,32 +113,53 @@ iapply(d, g)

When the output of `f` is a dataframe, we can bind all rows (or columns) quickly as follows:

```@example 4
```@example apply_df
using TidierIteration;
x = [1:4;]
h(x) = DataFrame(:x => x)
apply_dfr(x, h)
```

or
or

```@example 4
```@example apply_df
s = "abcd";
h2(s) = DataFrame(string(s) => rand(1))
h2("b")
apply_dfc(s, h2)
```

## p variables and one collection

We can apply a `p`-variable function to a collection of `p` elements as follows:

```@example papply
using TidierIteration
x = [
[1, 2], [3, 4], [5, 6]
]
f(x, y, z) = x + y + z
papply(x, f)
```

## API

<!-- ```@docs
```@docs
apply
apply2
apply_keys
walk
apply_dfc
apply_dfr
iapply
walk
iwalk
apply2
walk2
``` -->
papply
pwalk
```
28 changes: 18 additions & 10 deletions docs/src/flatten.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

The flatten family of functions aim to "reduce one level" of a object: if you have a dictionary where some values are also dictionaries, we "peel" this inner dictionary and spread it among the original dictionary. This is specially useful when parsing the output of a rest API and transforming it into a dataframe.

## Dictionaries
## Dictionaries and inner dictionaries

Consider the following nested dictionary describing a vehicle:

Expand All @@ -27,22 +27,23 @@ d1 = Dict(
We can flat the inner dictionaries as follows:

```@example 1
flatten_dict(d1)
d1
flatten(d1, n = 1)
```

We can apply the `flatten_dict` `n` consecutive times adding `n` to the end of the function call:
We can apply the `flatten` `n` consecutive times adding `n` to the end of the function call:

```@example 1
flatten_dict(d1, 2)
flatten(d1, n = 2)
```

Converting it to a dataframe is simple:

```@example 1
flatten_dict(d1, 2) |> DataFrame
flatten(d1, n = 1) |> DataFrame
```

In case of a vector of nested dictionaries, there is the `flatten_dicts_to_df`:
In case of a vector of nested dictionaries, there is the `flatten_dfr`:

```@example 1
d2 = Dict(
Expand All @@ -62,12 +63,19 @@ d2 = Dict(
ds = [d1, d2]
flatten_dicts_to_df(ds, 2)
flatten_dfr(ds, n = 2)
```

## Functions
If you want to convert the inner dictionaries/arrays to json (useful when saving to a relational database), use the function

```@examples 1
flatten_dfr_json(ds, n = 1)
```

## API

```@docs
flatten_dict
flatten_dicts_to_df
flatten
flatten_dfr
flatten_dfr_json
```
57 changes: 55 additions & 2 deletions docs/src/modify.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,59 @@
# Modify

Functions to modify a collection.
Functions to modify, filter and discard elements of a collection.

## Modifying

`modify` applies a function `f` to each element of `x`.

```@examples modify
x = [1:4;]
modify!(x, x->x^2)
x
```

It also work on dictionaries, keeping the keys intact:
```@examples modify
d = Dict(i => i for i in [1:4;])
modify(d, x->x^2)
```

We can also modify only when a function `p` is true:
```@examples modify
y = [1:6;]
modify_if(y, x->x^2, isodd)
```

## Filtering
We can discard some elements of `x` when a function `p` is false:

```@examples keep
x = [1:4;]
keep(x, isodd)
```

This is the same as base Julia `filter(p, x)`. It also work on dictionaries:

```@examples keep
d = Dict(i => i for i in [1:4;])
keep(x, isodd)
```

If we want to apply `p` to the keys of a dictionary, use
```@examples keep
d = Dict(i => i^2 for i in [1:4;])
keep_keys(d, isodd)
```

There is also the negation of `keep`: `discard`. It's definition is trivial: `discard(x, p) = keep(x, !p)`.

When we want to throw away "length zero elements", use `compact`:
```@examples keep
x = [1, [1, 2], nothing, [], ""]
compact(x)
```

## API

```@docs
modify
Expand All @@ -13,4 +66,4 @@ discard
discard!
compact
compact!
```
```
7 changes: 6 additions & 1 deletion docs/src/predicates.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
# Predicates

Predicates are functions that return `true` of `false`.
## API

```@docs
is_empty
is_non_empty
every
some
none
detect_index
detect
has_element
has_key
get_value
```
16 changes: 12 additions & 4 deletions src/TidierIteration.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,19 @@ using JSON3;
include("apply.jl");
export
apply,
apply2,
apply_keys,
apply_dfc,
apply_dfr,
iapply,
walk,
walk2;

apply2,
walk2,

iapply,
iwalk,

papply,
pwalk;

include("modify.jl");
export
Expand All @@ -27,6 +33,7 @@ export
modify_if!,
keep,
keep!,
keep_keys,
discard,
discard!,
compact,
Expand All @@ -42,7 +49,8 @@ export
detect_index,
detect,
has_element,
has_key;
has_key,
get_value;

include("adverbs.jl");
export
Expand Down
Loading

0 comments on commit 292c513

Please sign in to comment.