使用 jq 对数组中的元素对进行分组的最简洁方法

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

我要转换

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

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

我想到的最好的是(使用 1.5)

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

我可以使用更简洁或更高效或兼容 1.4 的解决方案吗?

就我个人而言,我会尝试像您那样做一些事情,从功能的角度来看,对我来说感觉是正确的。

但是还有其他表达方式。您可以利用这样一个事实,即在将数组转换为条目时,您会得到一个 index/value 对数组。

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

另一方面,您也可以只使用一系列数字创建数组的切片。我认为这可能比递归表现更好。

. as $arr | [ range(0; length/2) * 2 | $arr[.:.+2] ]

以下概括了任务,适用于 jq 1.4,在 jq 1.5 中的优化具有很高的性能,可用于实现 rho/1(如 R 的 "dim(z) <- c(3,5,100)" 和 APL 的 "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;

使用 "takes",可以使用以下方法完成任务:[takes(2)]

使用"rho",有几种可能性,特别是:

[rho( [ 2 ] )]

# or:

rho([3,2]) 

有关 "rho" 的更多信息,请参阅 https://github.com/stedolan/jq/issues/829

也许不是最简洁的方法,但这是使用 foreach 收集和发出值对的解决方案。

[
  foreach .[] as $x (
      []                                  # init
    ; if length>1 then [] else . end      # update
      | . + [$x]
    ; if length>1 then  . else empty end  # extract
  )
]