Skip to content

Commit b45426d

Browse files
committed
add aggregate
1 parent b5385a2 commit b45426d

File tree

1 file changed

+79
-0
lines changed
  • stdlib-candidate/std-rfc/aggregate

1 file changed

+79
-0
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
def aggregate-default-ops [] {
2+
{
3+
min: {math min},
4+
avg: {math avg},
5+
max: {math max},
6+
sum: {math sum},
7+
}
8+
}
9+
10+
def aggregate-col-name [col: cell-path, op_name: string]: [nothing -> string] {
11+
$col | split cell-path | get value | str join "." | $"($in)_($op_name)"
12+
}
13+
14+
# Run aggregations on output of `group-by --to-table`.
15+
#
16+
# # Example
17+
#
18+
# ```nushell
19+
# ls
20+
# | group-by type { get name | path parse | get extension } --to-table
21+
# | aggregate size
22+
# ```
23+
export def aggregate [
24+
--ops: record, # default = {min: {math min}, avg: {math avg}, max: {math max}, sum: {math sum}}
25+
...columns: cell-path, # columns to perform aggregations on
26+
]: [
27+
table<items: table> -> table<count: int>
28+
] {
29+
let IN = $in
30+
let md = metadata $in
31+
32+
# Validate input
33+
try {
34+
use std/assert
35+
assert ("items" in ($IN | first | columns))
36+
} catch {
37+
error make {
38+
msg: "input must be a table with `items` column",
39+
label: {
40+
text: "from here",
41+
span: $md.span
42+
},
43+
help: "Are you using `group-by` with `--to-table`?"
44+
}
45+
}
46+
47+
let agg_ops = $ops | default (aggregate-default-ops)
48+
49+
$IN
50+
| update items {|group|
51+
$columns | each {|col| # col: cell-path
52+
let column = try {
53+
$group.items | get $col
54+
} catch {
55+
let full_cellpath = (
56+
$col
57+
| split cell-path
58+
| prepend {value: items, optional: false}
59+
| into cell-path
60+
)
61+
error make {
62+
msg: $"Cannot find column '($full_cellpath)'",
63+
label: {
64+
text: "value originates here",
65+
span: $md.span
66+
},
67+
}
68+
}
69+
$agg_ops | items {|op_name, op| # op_name: string, op: closure
70+
$column | do $op | wrap (aggregate-col-name $col $op_name)
71+
}
72+
| reduce {|it| merge $it}
73+
}
74+
| reduce --fold {} {|it| merge $it}
75+
| insert count ($group.items | length)
76+
| roll right # put count as the first column
77+
}
78+
| flatten items
79+
}

0 commit comments

Comments
 (0)