Home Explore Blog CI



nushell

4th chunk of `cookbook/jq_v_nushell.md`
7a3f5aa7c6fee290901dee05e977946c1b749cefc43b880e0000000100001567
In `nu`, there is no built-in function equivalent to `recurse`. However, we can reuse the solution from [Filtering nested items](#filtering-nested-items) to extract the values to manipulate:

```nu
'{"data": {"value": 42, "nested": {"value": 24}}}'
| from json
| cherry-pick { |x| $x.value? }
| compact
| each { |x| $x * 5 }
# => ╭───┬─────╮
# => │ 0 │ 210 │
# => │ 1 │ 120 │
# => ╰───┴─────╯
```

### Filtering and mapping over nested items

In `jq`, to filter and map over a tree we do:

```sh
echo '{"data": {"values": [1, 2, 3], "nested": {"values": [4, 5, 6]}}}' |
jq -r 'walk(if type == "number" then . * 2 else . end)'
```

In `nu`, there is no built-in function to achieve this. See the [Appendix: Custom commands](#appendix-custom-commands) for an implementation of the command `filter-map` shown in the example below.

```nu
'{"data": {"values": [1, 2, 3], "nested": {"values": [4, 5, 6]}}}'
| from json
| filter-map {|value| if ($value | describe) == "int" { $value * 2 } else { $value }}
# => ╭──────┬──────────────────────────────────────╮
# => │      │ ╭────────┬─────────────────────────╮ │
# => │ data │ │        │ ╭───┬───╮               │ │
# => │      │ │ values │ │ 0 │ 2 │               │ │
# => │      │ │        │ │ 1 │ 4 │               │ │
# => │      │ │        │ │ 2 │ 6 │               │ │
# => │      │ │        │ ╰───┴───╯               │ │
# => │      │ │        │ ╭────────┬────────────╮ │ │
# => │      │ │ nested │ │        │ ╭───┬────╮ │ │ │
# => │      │ │        │ │ values │ │ 0 │  8 │ │ │ │
# => │      │ │        │ │        │ │ 1 │ 10 │ │ │ │
# => │      │ │        │ │        │ │ 2 │ 12 │ │ │ │
# => │      │ │        │ │        │ ╰───┴────╯ │ │ │
# => │      │ │        │ ╰────────┴────────────╯ │ │
# => │      │ ╰────────┴─────────────────────────╯ │
# => ╰──────┴──────────────────────────────────────╯
```

## Grouping and aggregating

### Grouping records by key

In `jq`, to group a list of records by key we do:

```sh
echo '[{"category": "A", "value": 10}, {"category": "B", "value": 20}, {"category": "A", "value": 5}]' |
jq -r 'group_by(.category)'
```

In `nu` we do:

```nu
'[{"category": "A", "value": 10}, {"category": "B", "value": 20}, {"category": "A", "value": 5}]'
| from json
| group-by --to-table category
# => ╭───┬───────┬──────────────────────────╮
# => │ # │ group │          items           │
# => ├───┼───────┼──────────────────────────┤
# => │ 0 │ A     │ ╭───┬──────────┬───────╮ │
# => │   │       │ │ # │ category │ value │ │
# => │   │       │ ├───┼──────────┼───────┤ │
# => │   │       │ │ 0 │ A        │    10 │ │
# => │   │       │ │ 1 │ A        │     5 │ │
# => │   │       │ ╰───┴──────────┴───────╯ │
# => │ 1 │ B     │ ╭───┬──────────┬───────╮ │
# => │   │       │ │ # │ category │ value │ │
# => │   │       │ ├───┼──────────┼───────┤ │
# => │   │       │ │ 0 │ B        │    20 │ │
# => │   │       │ ╰───┴──────────┴───────╯ │
# => ╰───┴───────┴──────────────────────────╯
```

Note that `--to-table` was added to Nushell in [version 0.87.0](blog/2023-11-14-nushell_0_87_0.html). Before that you had to [`transpose`](/commands/docs/transpose) the record resulting from `group-by` which was substantially slower for large sets.

### Aggregating grouped values

In `jq`, to aggregate grouped values we do:

```sh
echo '[{"category": "A", "value": 10}, {"category": "B", "value": 20}, {"category": "A", "value": 5}]' |
jq -r 'group_by(.category) | map({category: .[0].category, sum: map(.value) | add})'
```

In `nu` we do:

```nu
'[{"category": "A", "value": 10}, {"category": "B", "value": 20}, {"category": "A", "value": 5}]'
| from json
| group-by --to-table category
| update items { |row| $row.items.value | math sum }
| rename category sum
```

### Filtering after aggregating

In `jq`, to filter after aggregating we do:

```sh
echo '[{"category": "A", "value": 10}, {"category": "B", "value": 20}, {"category": "A", "value": 5}]' |
jq -r 'group_by(.category) | map({category: .[0].category, sum: (map(.value) | add)}) | .[] | select(.sum > 17)'

Title: Filtering and Mapping Nested Items, Grouping and Aggregating: jq vs Nushell
Summary
This section compares how `jq` and Nushell handle filtering and mapping over nested items, as well as grouping and aggregating data. It shows how `jq` uses the `walk` function for filtering and mapping, while Nushell utilizes a custom command `filter-map`. It then demonstrates how both tools group records by key, aggregate grouped values, and filter after aggregation. The Nushell examples highlight the `group-by`, `update`, `rename`, and `where` commands.