Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
lukasheinrich opened this issue Jul 17, 2018 · 8 comments
Open

Comments

@lukasheinrich
Copy link

lukasheinrich commented Jul 17, 2018

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
Copy link
Collaborator

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
Copy link

seh commented Oct 7, 2018

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
Copy link
Collaborator

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
Copy link

buremba commented Jul 19, 2019

@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
Copy link

buremba commented Jul 19, 2019

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
Copy link
Collaborator

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
Copy link

doronbehar commented Sep 16, 2020

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
Copy link

alexei-matveev commented May 7, 2021

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants