Algorithms#
Nushell’s table operations replace the bulk of what bash
operators reach for sort, uniq, awk, and jq to
do. sort-by, group-by, uniq, where, reduce,
and join cover the patterns operators run into most. For
genuine algorithm work, Nu has lists, recursion, and closures
the same as any modern scripting language.
Search#
Linear search over a list.
def contains [needle: any, haystack: list] {
$haystack | any { |x| $x == $needle }
}
let items = [red green blue]
contains green $items # true
Operator form. in is membership; =~ is regex match.
"green" in $items # true
$items | where $it =~ 'gr' # [green]
$items | find green # [green]
Filter#
where is the workhorse. The predicate can reference $it
(implicit current value) or take a closure with a named
parameter.
ls | where size > 1MB
ls | where modified > (date now) - 1day
open users.json | where age > 30 and region == "us-east"
Sorting#
sort (for lists) and sort-by (for tables) cover the
standard cases. Multi-key, descending, natural, case-
insensitive.
[10 2 33 4 5] | sort # [2 4 5 10 33]
[10 2 33 4 5] | sort --reverse # [33 10 5 4 2]
["B" "a" "C"] | sort --insensitive # [a B C]
$rows | sort-by size
$rows | sort-by size --reverse
$rows | sort-by region name # multi-key
ls | sort-by --natural name # 2 < 10 < 100
Dedup#
uniq works on lists; uniq-by works on tables (dedupe by
column). uniq --count returns the count per distinct value.
[a b a c b a] | uniq # [a b c]
[a b a c b a] | uniq --count # table with value+count
$rows | uniq-by region # one row per region
Grouping#
group-by produces a record whose keys are the group values
and whose values are tables of matching rows. transpose then
flattens that back into “name + group” rows the way
Group-Object does.
$users | group-by region
$users
| group-by region
| transpose region members
| upsert count { |row| $row.members | length }
| sort-by count --reverse
Joining#
Tables can join on a common column. The standard relational operation, in shell.
let users = [[id name]; [1 alice] [2 bob] [3 carol]]
let roles = [[user_id role]; [1 admin] [3 viewer]]
$users | join $roles id user_id --left
Aggregate#
math is the namespace. math sum, math avg,
math min, math max, math median, math stddev.
[10 20 30 40] | math sum # 100
[10 20 30 40] | math avg # 25
ls | get size | math sum
For a table grouped by column, combine group-by and
each.
$users
| group-by region
| transpose region rows
| each { |g| {region: $g.region, total_age: ($g.rows | get age | math sum)} }
Reduce#
reduce folds a list into a single value with a closure.
[1 2 3 4 5] | reduce { |it, acc| $acc + $it } # 15
[1 2 3 4 5] | reduce --fold 1 { |it, acc| $acc * $it } # factorial 120
Recursion#
def factorial [n: int] {
if $n <= 1 { 1 } else { $n * (factorial ($n - 1)) }
}
factorial 5 # 120
For numeric work, the reduce form is faster (no recursion
overhead). For tree traversal where recursion is natural, Nu
holds up like any modern language; it does not have tail-call
optimization, so very deep recursions hit a stack limit.
References#
Structures for the lists, records, and tables these algorithms operate on.
I/O and Pipelines for the parallel
par-eachform when the work is independent.