jq icon indicating copy to clipboard operation
jq copied to clipboard

Docs: `sort_by()` doesn't mention sorting by multiple keys of an object

Open jbrains opened this issue 2 years ago • 1 comments

I wanted to sort an array of objects by multiple keys (to break ties in the first key). The Manual doesn't describe this at all, but a Stack Overflow article showed that it works with sort_by(key1, key2, ...).

I propose to add this to the Manual.

Based on a comment from https://github.com/stedolan/jq/issues/2466 I'm just going to submit a PR and wait patiently until someone merges it. No rush, since anyone who needs to know this will almost certainly eventually find the information.

jbrains avatar Aug 24 '22 17:08 jbrains

Great addition i think. I didn't know about it and based on the test cases when it was added https://github.com/stedolan/jq/commit/11965aaa2e9cf2b09c431e682cdc459b99de60fb it is intentional. Kind of neat. Also the implementation is neat, the output from the filter is collected in an array [f] so the compare will be between to arrays.

wader avatar Aug 24 '22 18:08 wader

im against var agrs. i want better to have additional sort_by/2, where second parameter can define isDescending order

chaining those sort_by/2 with pipe can create efficient multi-sorting pipeline, without extra use of reverse|sort_by|reverse for not breaking stablesort

sergeysosivio avatar Oct 13 '22 15:10 sergeysosivio

Interesting. So in my case of parsing kscreen-doctor --json list of outputs (screens, monitors in human-speak) I has to do this to sort them first by enabled key and then by id:

outputs=(${(f)"$(
    kscreen-doctor --json |
    jq --raw-output '
        .outputs |
        sort_by([.connected | not], [.name]) |
        .[] |
        [.id, .name, .connected] |
        .[]
    ')"})

I'm a bit surprised that it didn't work as sort_by([.connected | not, .name]) without separate arrays, and I don't fully understand what is going on. But, hey, it works!

ratijas avatar Nov 13 '22 13:11 ratijas

I'm a bit surprised that it didn't work as sort_by([.connected | not, .name]) without separate arrays, and I don't fully understand what is going on. But, hey, it works!

Hi, you might want (.connected | not), .name else .name will index whatever .connected is.

$ jq -nc '{"connected": {"name": "b"}} | [.connected | not, .name]'
[false,"b"]

(but if .connected is bool i think you should have ende up with the error Cannot index boolean with string "name")

wader avatar Nov 15 '22 12:11 wader