}
}
+static jv f_sort_by_impl(jv input, jv keys) {
+ if (jv_get_kind(input) == JV_KIND_ARRAY &&
+ jv_get_kind(keys) == JV_KIND_ARRAY &&
+ jv_array_length(jv_copy(input)) == jv_array_length(jv_copy(keys))) {
+ return jv_sort(input, keys);
+ } else {
+ return type_error2(input, keys, "cannot be sorted, as they are not both arrays");
+ }
+}
+
+static jv f_group_by_impl(jv input, jv keys) {
+ if (jv_get_kind(input) == JV_KIND_ARRAY &&
+ jv_get_kind(keys) == JV_KIND_ARRAY &&
+ jv_array_length(jv_copy(input)) == jv_array_length(jv_copy(keys))) {
+ return jv_group(input, keys);
+ } else {
+ return type_error2(input, keys, "cannot be sorted, as they are not both arrays");
+ }
+}
+
static jv f_type(jv input) {
jv out = jv_string(jv_kind_name(jv_get_kind(input)));
jv_free(input);
{(cfunction_ptr)f_type, "type", 1},
{(cfunction_ptr)f_add, "add", 1},
{(cfunction_ptr)f_sort, "sort", 1},
+ {(cfunction_ptr)f_sort_by_impl, "_sort_by_impl", 2},
+ {(cfunction_ptr)f_group_by_impl, "_group_by_impl", 2},
};
static struct symbol_table cbuiltins = {function_list, sizeof(function_list)/sizeof(function_list[0])};
static const char* jq_builtins[] = {
"def map(f): [.[] | f];",
"def select(f): if f then . else empty end;",
+ "def sort_by(f): _sort_by_impl(map([f]));",
+ "def group_by(f): _group_by_impl(map([f]));",
};
input: '[1, "1", [1]]'
output: ['"1"', '"1"', '"[1]"']
+ - title: `sort, sort_by`
+ body: |
+
+ The `sort` functions sorts its input, which must be an
+ array. Values are sorted in the following order:
+
+ * `null`
+ * `false`
+ * `true`
+ * numbers
+ * strings, in alphabetical order (by unicode codepoint value)
+ * arrays, in lexical order
+ * objects
+
+ The ordering for objects is a little complex: first they're
+ compared by comparing their sets of keys (as arrays in
+ sorted order), and if their keys are equal then the values
+ are compared key by key.
+
+ `sort_by` may be used to sort by a particular field of an
+ object, or by applying any jq filter. `sort_by(foo)`
+ compares two elements by comparing the result of `foo` on
+ each element.
+
+ examples:
+ - program: 'sort'
+ input: '[8,3,null,6]'
+ output: ['[null,3,6,8]']
+ - program: 'sort_by(.foo)'
+ input: '[{"foo":4, "bar":10}, {"foo":3, "bar":100}, {"foo":2, "bar":1}]'
+ output: ['[{"foo":2, "bar":1}, {"foo":3, "bar":100}, {"foo":4, "bar":10}]']
+
+ - title: `group_by`
+ body: |
+
+ `group_by(.foo)` takes as input an array, groups the
+ elements having the same `.foo` field into separate arrays,
+ and produces all of these arrays as elements of a larger
+ array, sorted by the value of the `.foo` field.
+
+ Any jq expression, not just a field access, may be used in
+ place of `.foo`. The sorting order is the same as described
+ in the `sort` function above.
+
+ examples:
+ - program: 'group_by(.foo)'
+ input: '[{"foo":1, "bar":10}, {"foo":3, "bar":100}, {"foo":1, "bar":1}]'
+ output: ['[[{"foo":1, "bar":10}, {"foo":1, "bar":1}], [{"foo":3, "bar":100}]]']
+
- title: `contains`
body: |
end
input: 2
output: ['"many"']
+
+ - title: `>, >=, <=, <`
+ body: |
+
+ The comparison operators `>`, `>=`, `<=`, `<` return whether
+ their left argument is greater than, greater than or equal
+ to, less than or equal to or less than their right argument
+ (respectively).
+
+ The ordering is the same as that described for `sort`, above.
+
+ examples:
+ - program: '. < 5'
+ input: 2
+ output: ['true']
- title: and/or/not
body: |
sort
[42,[2,5,3,11],10,{"a":42,"b":2},{"a":42},true,2,[2,6],"hello",null,[2,5,6],{"a":[],"b":1},"abc","ab",[3,10],{},false,"abcd",null]
[null,null,false,true,2,10,42,"ab","abc","abcd","hello",[2,5,3,11],[2,5,6],[2,6],[3,10],{},{"a":42},{"a":42,"b":2},{"a":[],"b":1}]
+
+(sort_by(.b) | sort_by(.a)), sort_by(.a, .b), sort_by(.b, .c), group_by(.b), group_by(.a + .b - .c == 2)
+[{"a": 1, "b": 4, "c": 14}, {"a": 4, "b": 1, "c": 3}, {"a": 1, "b": 4, "c": 3}, {"a": 0, "b": 2, "c": 43}]
+[{"a": 0, "b": 2, "c": 43}, {"a": 1, "b": 4, "c": 14}, {"a": 1, "b": 4, "c": 3}, {"a": 4, "b": 1, "c": 3}]
+[{"a": 0, "b": 2, "c": 43}, {"a": 1, "b": 4, "c": 14}, {"a": 1, "b": 4, "c": 3}, {"a": 4, "b": 1, "c": 3}]
+[{"a": 4, "b": 1, "c": 3}, {"a": 0, "b": 2, "c": 43}, {"a": 1, "b": 4, "c": 3}, {"a": 1, "b": 4, "c": 14}]
+[[{"a": 4, "b": 1, "c": 3}], [{"a": 0, "b": 2, "c": 43}], [{"a": 1, "b": 4, "c": 14}, {"a": 1, "b": 4, "c": 3}]]
+[[{"a": 1, "b": 4, "c": 14}, {"a": 0, "b": 2, "c": 43}], [{"a": 4, "b": 1, "c": 3}, {"a": 1, "b": 4, "c": 3}]]