jsonnet icon indicating copy to clipboard operation
jsonnet copied to clipboard

iterating through objects as key value pairs (cf. pythons .items())

Open lukasheinrich opened this issue 7 years ago • 8 comments
trafficstars

sometimes it's useful to process objects by iterating through the key value pairs

python has

obj = {"a": 1, "b": 2}
{k:v*2 for k,v in obj.items()}

jq has

echo '{"a": 1, "b": 2}'|jq '[to_entries[]|{key: .key, value: (.value * 2)}]|from_entries'

is there something similar in jsonnet? it seems like the list and object comprehensions could return (k,v) tuples if the right hand side is an object

lukasheinrich avatar Jul 17 '18 21:07 lukasheinrich

You can achieve that using std.objectFields or std.objectFieldsAll to get list of keys (depending on whether you want to include hidden fields). If you need both keys and values, there's no builtin function, but it's pretty simple to write yourself.

local keysAndValues(obj) = std.map(function(x) [x, obj[x]], objectFields(obj))

(note: I haven't tested it yet)

What you describe could be a nice shortcut.

@sparkprime Perhaps we should add something like keysAndValues to stdlib

sbarzowski avatar Jul 19 '18 16:07 sbarzowski

Though it wouldn't matter for the usual small objects, implementing this as a native function would save the lookup for each key to retrieve its corresponding value (obj[x] above).

seh avatar Oct 07 '18 13:10 seh

You can do {k: obj[k]*2 for k in std.objectFields(obj)}

Iteration over objects would be nice too {k: e for k, v in ...} And it's just syntax sugar to implement it.

sparkprime avatar Oct 07 '18 18:10 sparkprime

@sparkprime The syntax sugar that you gave as an example is not implemented yet, right? It throws the following exception: object comprehensions can only have [e] fields.

buremba avatar Jul 19 '19 10:07 buremba

It looks like the syntax is as follows:{ [key]: last_values[key] for key in std.objectFields(last_values) by looking at std.jsonnet. It would be great if we can add it to the documentation.

P.S: Given that we have this syntax, why don't we close the issue? There are more than 100 open issues at the moment. 😬

buremba avatar Jul 19 '19 10:07 buremba

The issue is about matching the python feature of for k, v in obj, which I think would be useful even though a simple work around is to loop over the fields doing obj[k] each time. It is indeed not implemented yet.

sparkprime avatar Jul 19 '19 16:07 sparkprime

I also noticed the lack of such a function, and I was surprised that std.mapWithKey didn't generate an array. I opened https://stackoverflow.com/questions/63915576/jsonnet-std-mapwithkey-not-generating-an-array/63915745#63915745 and answered my self based upon @sbarzowski's response.

Also, I noticed there's a lack of std.objectValues which is a bit annoying as well, but once again, it can be worked around if using a std.map and std.objetFields.

doronbehar avatar Sep 16 '20 08:09 doronbehar

The order of [k , v] pairs could be a problem for stable generated configs. FWIW, Clojure implements "Sequential Interface" for Maps/Dictionaries/Objects too, the order is also not guaranteed, of course... Sorted Sets eventually? I heard you can even compare arrays ...

Came here from google looking for "jsonnet iterate over object". For my immediate case it will be std.mapWithKey() eventually ...

alexei-matveev avatar May 07 '21 10:05 alexei-matveev