'jq - reduce array of paths using subpaths
Assume the following JSON data:
{
"results": [
{
"path": "other/foo/1.15.1",
"modified": "2022-02-09T13:45:34.638Z"
},
{
"path": "other/foo/1.15.0",
"modified": "2022-02-09T10:00:40.681Z"
},
{
"path": "a/b/foo/1.0.3-SNAPSHOT",
"modified": "2022-03-04T19:07:30.262Z"
},
{
"path": "a/b/c/0.1.1",
"modified": "2022-01-10T15:12:00.597Z"
},
{
"path": "a/b/c/0.1.0",
"modified": "2022-01-07T18:05:23.158Z"
},
{
"path": "a/b/c/0.0.9",
"modified": "2021-12-06T10:29:31.161Z"
}
]
}
And also assume, that it is descendingly sorted first per path then per modified.
Now, for every path without its last part, I would like to find only the latest ones according to the modified field (which are always on the top because of the sorting). Then, output that path including its last part again.
In other words, for this example data the output should be:
other/foo/1.15.1
a/b/foo/1.0.3-SNAPSHOT
a/b/c/0.1.1
Solution 1:[1]
Extract the common path to a new field, group the objects by the new field, and select the one with the maximal modified field.
jq -r '[.results[]
| .short = .path[0:(.path | rindex("/"))]
]
| group_by(.short)[]
| max_by(.modified).path
' file.json
Solution 2:[2]
I came up with a solution using foreach and regular expressions, based on this answer https://stackoverflow.com/a/29829035/1851290
jq -n -r 'foreach (inputs | .results| .[]) as $k (
{};
.[$k.path | sub("/[^/]*$"; "")]+=1;
if .[$k.path | sub("/[^/]*$"; "")]==1 then
$k.path
else
empty
end
)'
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | choroba |
| Solution 2 | Danny Lo |
