Create object from array of keys and values
Asked Answered
U

5

9

I've been banging my head against the wall for several hours on this and just can't seem to find a way to do this. I have an array of keys and an array of values, how can I generate an object? Input:

[["key1", "key2"], ["val1", "val2"]]

Output:

{"key1": "val1", "key2": "val2"}
Upstream answered 23/1, 2015 at 5:18 Comment(0)
U
10

Resolved this on github:

.[0] as $keys |
.[1] as $values |
reduce range(0; $keys|length) as $i  ( {}; . + { ($keys[$i]): $values[$i] })
Upstream answered 23/1, 2015 at 20:3 Comment(0)
C
3

The current version of jq has a transpose filter that can be used to pair up the keys and values. You could use it to build out the result object rather easily.

transpose | reduce .[] as $pair ({}; .[$pair[0]] = $pair[1])
Carbine answered 23/1, 2015 at 15:32 Comment(3)
Thanks Jeff, I'm not sure that quite works though. I played around with it and the first portion seems to generate every key/val combination, but then the from_entries seems to override the right key/val pair with the wrong one. This is what I'm getting: { "key1": "val2", "key2": "val2" }Upstream
Ah dang it, I knew that cross products might be an issue. When I checked it I thought it was fine. It's too bad there isn't a builtin zip filter. Then it would be trivial.Carbine
There is no need to use from_entries. That is: transpose | map({ (.[0]): .[1] }) | addPayday
P
2

Just to be clear:

(0) Abdullah Jibaly's solution is simple, direct, efficient and generic, and should work in all versions of jq;

(1) transpose/0 is a builtin in jq 1.5 and has been available in pre-releases since Oct 2014;

(2) using transpose/0 (or zip/0 as defined above), an even shorter but still simple, fast, and generic solution to the problem is:

transpose | map( {(.[0]): .[1]} ) | add

Example:

$ jq 'transpose | map( {(.[0]): .[1]} ) | add'

Input:

[["k1","k2","k3"], [1,2,3] ]

Output:

{
  "k1": 1,
  "k2": 2,
  "k3": 3
}
Payday answered 5/9, 2015 at 17:26 Comment(0)
V
1

Scratch this, it doesn't actually work for any array greater than size 2.

[map(.[0]) , map(.[1])] | map({(.[0]):.[1]}) | add

Welp, I thought this would be easy, having a little prolog experience... oh man. I ended up banging my head against a wall too. Don't think I'll ever use jq ever again.

Valentino answered 23/1, 2015 at 6:24 Comment(2)
Thanks for the effort! I actually found the answer (see updated Q).Upstream
It's actually not too bad if we had some of the more typical functional methods such as zip built in. Fortunately it's not too bad implementing it.Carbine
C
0

Here is a solution which uses reduce with a state object holding an iteration index and a result object. It iterates over the keys in .[0] setting corresponding values in the result from .[1]

  .[1] as $v
| reduce .[0][] as $k (
   {idx:0, result:{}}; .result[$k] = $v[.idx] | .idx += 1
  )
| .result
Catacomb answered 3/8, 2017 at 17:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.