Reputation: 21
I have following test data and am trying to jq sort in descending order by the highest weight, but having trouble with these decimal points, which the sort seems to ignore?
[
{
"name": "train",
"amount": "4",
"weight": "89129.70000000"
},
{
"name": "plane",
"amount": "200",
"weight": "819002.68900000"
},
{
"name": "car",
"amount": "27",
"weight": "527561695272.42000000"
},
{
"name": "bike",
"amount": "14",
"weight": "9914795.00000000"
},
{
"name": "truck",
"amount": "92",
"weight": "999147.00000000"
}
]
jq -r 'map(select(.weight)) | sort_by(.weight)[] | [.name,.weight]'
will output it incorrectly, it seems to ignore the decimal point eg.
[
"car",
"527561695272.42000000"
]
[
"plane",
"819002.68900000"
]
[
"train",
"89129.70000000"
]
[
"bike",
"9914795.00000000"
]
[
"truck",
"999147.00000000"
]
i've tried a few things and have managed to sort it via:
jq '[.[].weight] | sort_by( split(".") | map(tonumber) ) | reverse'
which will sort output correctly:
[
"527561695272.42000000",
"9914795.00000000",
"999147.00000000",
"819002.68900000",
"89129.70000000"
]
Think its because all outputs come in strings, and so need to use the tonumber function. However, from what I'm doing there, I'm not sure how to get jq to output the full objects, or other things like .name as in the first example. keep getting errors, seem to have put myself into a corner.
Ideally I just want the full output the objects but correctly sorted descending by weight, i.e. the full data, just sorted.
Upvotes: 1
Views: 438
Reputation: 18106
Let's consider the following versions as the current versions:
jq
: 1.6
.but having trouble with these decimal points, which the sort seems to ignore?
Please, note that for some reason to represent numbers you are using string values instead of numeric values.
For example:
"weight": "89129.70000000"
Please, note that the number itself is in double quotes: this makes it a string value.
I would like to recommend you to correct the input data, so that numbers are represented by numeric values.
For example:
"weight": 89129.7
Please, consider using the sort_by()
function with the appropriate path expression.
sort_by(foo)
compares two elements by comparing the result offoo
on each element.
Since weight
values are represented by string values (i.e. without taking into account the recommendation), it is necessary to perform the tonumber
conversion to sort them as numeric values.
jq -r 'sort_by(.weight | tonumber) | reverse' input.json
[
{
"name": "car",
"amount": "27",
"weight": "527561695272.42000000"
},
{
"name": "bike",
"amount": "14",
"weight": "9914795.00000000"
},
{
"name": "truck",
"amount": "92",
"weight": "999147.00000000"
},
{
"name": "plane",
"amount": "200",
"weight": "819002.68900000"
},
{
"name": "train",
"amount": "4",
"weight": "89129.70000000"
}
]
If weight
values were represented by numeric values (i.e. taking into account the recommendation), it would not be necessary to perform the tonumber
conversion:
jq -r 'sort_by(.weight) | reverse' input.json
Upvotes: 2