google / jsonnet

Jsonnet - The data templating language
http://jsonnet.org
Apache License 2.0
7k stars 440 forks source link

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

Open lukasheinrich opened 6 years ago

lukasheinrich commented 6 years ago

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

sbarzowski commented 6 years ago

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

seh commented 6 years ago

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).

sparkprime commented 6 years ago

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.

buremba commented 5 years ago

@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 commented 5 years ago

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. 😬

sparkprime commented 5 years ago

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.

doronbehar commented 4 years ago

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.

alexei-matveev commented 3 years ago

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 ...