Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Most concise way to group pairs of elements in an array with jq

Tags:

jq

I want to convert

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

to

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

The best I've come up with is (using 1.5)

[recurse(.[2:];length>1)[0:2]]

Is there a more concise or more performant or 1.4 compatible solution I could use instead?

like image 250
Ed Thomas Avatar asked Dec 11 '25 19:12

Ed Thomas


2 Answers

Personally, I would have tried to do something like you did, to me that feels right from a functional perspective.

But there are other ways this could be expressed. You could take advantage of the fact that when converting an array to entries, you get an array of index/value pairs.

to_entries | group_by(.key/2 | floor) | map(map(.value))

On the other hand, you could also just create slices of the array using a range of numbers. I think this may perform better than recursing.

. as $arr | [ range(0; length/2) * 2 | $arr[.:.+2] ]
like image 192
Jeff Mercado Avatar answered Dec 16 '25 00:12

Jeff Mercado


The following generalizes the task, works with jq 1.4, is highly performant with the optimizations in jq 1.5, and can be used to implement rho/1 (like R's "dim(z) <- c(3,5,100)" and APL's "A⍴B"):

# Input: an array
# Output: a stream of arrays
# If the input is [] then the output stream is empty,
# otherwise it consists of arrays of length n, each array consisting
#  of successive elements from the input array, padded with nulls.
def takes(n):
  def _takes:
    if length == 0 then empty
    elif length < n then .[n-1] = null
    else .[0:n], (.[n:] | _takes)
    end;
  _takes;

Using "takes", one could fulfill the task using: [takes(2)]

Using "rho", there are several possibilities, notably:

[rho( [ 2 ] )]

# or:

rho([3,2]) 

For more about "rho", see https://github.com/stedolan/jq/issues/829

like image 36
peak Avatar answered Dec 16 '25 02:12

peak



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!