Jq: get last element from array

Created on 28 Jul 2014  Â·  19Comments  Â·  Source: stedolan/jq

For example i have array like:

[
{
  "type": "strip",
  "output": "output/debian-7-x86_64-strip/"
},
{
  "type": "compress",
  "format": "gzip",
  "output": "output/debian-7-x86_64-compress/"
}
]

How can i get "output" value from last element from array? I don't known count of elements it may contain 1 or 20 elements, but i need only last.

bug

Most helpful comment

What you want is .[-1].output. Negative array indexing works just as it does in python, so .[-1] gives you the last element. Then you just ask for the output field of that object and you're done.

All 19 comments

What you want is .[-1].output. Negative array indexing works just as it does in python, so .[-1] gives you the last element. Then you just ask for the output field of that object and you're done.

Thanks. I'm create before more complex method using post-processors"[(."post-processors" | length) -1].output
This is more simple solution. Thanks!

This is not works in case of only one elements i have this:

jq '."post-processors" | .[0]' current-x86_64.json                                                                                                                            
{
  "type": "compress",
  "format": "gzip",
  "output": "output/coreos-current-x86_64-compress/"
}
jq '."post-processors" | .[-1]' current-x86_64.json 
null

@vtolstov wrote:

jq '."post-processors" | .[-1]' current-x86_64.json

It is only recently that jq has begun to support the use of quotation marks in this way. But you are correct -- since the key name has a "-" in it, you have to be a bit careful. The robust way to do what you want is:

jq '.["post-processors"] | .[length-1]' current-x86_64.json 

If the key name were post_processors (with an underscore) you could write:

jq '.post_processors | .[-1]' current-x86_64.json 

[THE ABOVE HAS BEEN EDITED TO TAKE INTO ACCOUNT DIFFERENCES BETWEEN DIFFERENT VERSIONS OF jq]

@pkoppstein this is also not works:

jq '.["post-processors"] | .[-1]' current-x86_64.json
null

jq --version
jq-1.3-202-g5fb82d1

2014-07-28 19:33 GMT+04:00 pkoppstein [email protected]:

jq '.["post-processors"] | .[-1]' current-x86_64.json

This is also not works:

jq '.["post-processors"] | .[-1]' current-x86_64.json
null
jq --version
jq-1.3-202-g5fb82d1

Vasiliy Tolstov,
e-mail: v.[email protected]
jabber: [email protected]

In jq 1.4 ."foo" does work for indexing objects.

But yes, I'm seeing a problem with negative indices:

$ jq -c -n '[range(0;5)][-2:-1]'
[3]
$ jq -n '[range(0;5)][-1]'
null
$ 

@vtolstov - As you see, the use of negative indexing is not robust between different versions of jq.

The most robust approach is to use " | .[length - 1]", e.g.

jq -n '[range(0;5)] | .[length-1]'
4

Sometimes, if a is an array, then the idiom "[(a | length) - 1]" can be helpful, e.g.

$ jq -n -c -M '[range(0;5)] | . as $a | setpath([($a|length)-1]; 123)'
[0,1,2,3,123]

By the way, when posting questions, it is generally best either to use a very simple example (as above with "jq -n"), or at least to be explicit about the data.

Negative array indices do work in master, just not in 1.4. Checking 1.3... negative array indices didn't work either. This is good news then, for I really want the last element to be addressed with -2, so that -1 can be used for appending.

I'll have to figure out what's causing this in 1.3 and 1.4, and why it works in master. If the bug is general enough then I'll just change the meaning of -1 to be the element after the last, to make .[-1] = ... work for appending.

It works in master because I fixed it a while back. jv_get() didn't handle negative indices, but the slice code did.

PR #462 was where it happened. Commit d0ca11d.

Ahh, thanks @wtlangford. Yes, now I remember.

@nicowilliams wrote:

... I'll just change the meaning of -1 to be the element after the last ...

Please don't. Or at least please consult with others. There are other ways to refer to the position after the last element. For example, instead of -1 you could use [0], and more generally [ n ] would refer to n positions after the last element. Thus a[ [n] ] = e would be shorthand for a | setpath([length + n]; e)

@pkoppstein That's a thought. I'll think about it.

@nicowilliams -1 definitely should not be after the last element. I know of no language that does this, but I know of several (Python, Ruby) that make [-1] the last element. It's easy to explain as well: [-n] is equivalent to [length-n], with no silly +/-1 to take care of.

Thanks all =)

@nicowilliams I agree with all, -1 should be the last element.

You could also reverse the array and pick the first element:

For the input

[
  [ "a" ],
  [ 1, "b" ],
  [ 2, 1, "c" ],
  []
]

jq '(.[] | reverse)[0]' outputs

"a"
"b"
"c"
null
Was this page helpful?
0 / 5 - 0 ratings

Related issues

rubensayshi picture rubensayshi  Â·  3Comments

ve3ied picture ve3ied  Â·  4Comments

tbelaire picture tbelaire  Â·  4Comments

tischwa picture tischwa  Â·  4Comments

geoffeg picture geoffeg  Â·  3Comments