Skip to content

Commit

Permalink
builtin: Add chunk_by, count_by and debug
Browse files Browse the repository at this point in the history
  • Loading branch information
wader committed Sep 12, 2021
1 parent f322e78 commit 77f97aa
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 15 deletions.
4 changes: 0 additions & 4 deletions dev/snippets.jq
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# same as group_by but counts
def count_by(exp):
group_by(exp) | map([(.[0] | exp), length]);

def protobuf_to_value:
.fields | map({(.name | tostring): (.enum // .value)}) | add;

Expand Down
6 changes: 6 additions & 0 deletions doc/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ notable is support for arbitrary-precision integers.
### Functions

- All standard library functions from jq
- `chunk/1`, `chunk_by/1` like `group` but groups consecutively on condition.
- `count_by` like `group_by` but counts groups lengths.
- `debug/1` like `debug/0` but uses arg to produce debug message. `{a: 123} | debug({a}) | ...`.
- `path_to_expr` from `["key", 1]` to `".key[1]"`.
- `expr_to_path` from `".key[1]"` to `["key", 1]`.
- `diff/2` produce diff object between two values.
- `open` open file for reading
- `probe` or `decode` try to automatically detect format and decode
- `mp3`, `matroska`, ..., `<name>`, `decode([name])` try decode as format
Expand Down
37 changes: 37 additions & 0 deletions pkg/interp/funcs.jq
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,43 @@ def trim: capture("^\\s*(?<str>.*?)\\s*$"; "").str;
# does +1 and [:1] as " "*0 is null
def rpad($s; $w): . + ($s * ($w+1-length))[1:];

# like `group` but groups consecutively on condition
def chunk_by(f):
( . as $a
| length as $l
| if $l == 0 then []
else
( [ foreach $a[] as $v (
{cf: ($a[0] | f), index: 0, start: 0, extract: null};
( ($v | f) as $vf
| (.index == 0 or (.cf == $vf)) as $equal
| if $equal then
( .extract = null
)
else
( .cf = $vf
| .extract = [.start, .index]
| .start = .index
)
end
| .index += 1
);
( if .extract then .extract else empty end
, if .index == $l then [.start, .index] else empty end
)
)
]
| map($a[.[0]:.[1]])
)
end
);
# [1, 2, 2, 3] => [[1], [2, 2], [3]
def chunk: chunk_by(.);

# same as group_by but counts
def count_by(exp):
group_by(exp) | map([(.[0] | exp), length]);

# helper to build path query/generate functions for tree structures with
# non-unique children, ex: mp4_path
def tree_path(children; name; $v):
Expand Down
37 changes: 26 additions & 11 deletions pkg/interp/funcs_test.jq
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
include "assert";
include "funcs";

[
".",
".a",
".a[0]",
".a[123].bb",
".[123].a",
".[123][123].a",
".\"b b\"",
".\"a \\\\ b\"",
".\"a \\\" b\""
][] | assert("\(.) | expr_to_path | path_to_expr"; .; expr_to_path | path_to_expr)
(
([
".",
".a",
".a[0]",
".a[123].bb",
".[123].a",
".[123][123].a",
".\"b b\"",
".\"a \\\\ b\"",
".\"a \\\" b\""
][] | assert("\(.) | expr_to_path | path_to_expr"; .; expr_to_path | path_to_expr))
,
([
[[], []],
[[1], [[1]]],
[[1,1], [[1,1]]],
[[1,1,2], [[1,1],[2]]],
[[1,1,2,2], [[1,1],[2,2]]],
[[1,2,2,1], [[1],[2,2],[1]]]
][] | assert("\(.) | chunk"; .[1]; .[0] | chunk))
,
([
[[{a:1},{a:1},{a:2}], [[{a:1},{a:1}],[{a:2}]]]
][] | assert("\(.) | chunk_by"; .[1]; .[0] | chunk_by(.a)))
)
1 change: 1 addition & 0 deletions pkg/interp/internal.jq
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ def debug:
( ((["DEBUG", .] | tojson), "\n" | stderr)
, .
);
def debug(f): . as $c | f | debug | $c;

# eval f and finally eval fin even on empty or error
def finally(f; fin):
Expand Down

0 comments on commit 77f97aa

Please sign in to comment.