May I ask:
What's the idiomatic way to retrieve values from nested dictionaries? (((dict1 at: 'key1') at: 'key2') at: 'key3') Are all the brackets really necessary? BR Mike |
> On Apr 24, 2017, at 14:42, Markus Böhm <[hidden email]> wrote: > > May I ask: > What's the idiomatic way to retrieve values from nested dictionaries? > > (((dict1 at: 'key1') at: 'key2') at: 'key3') > > Are all the brackets really necessary? I think so, without the parenthesis, it is interpreted as one message at:at:at: If you use it a lot, you may want to convert the dictionary structure into domain objects. Juraj > > BR Mike |
In reply to this post by Markus Böhm-2
Le 24/04/2017 à 19:42, Markus Böhm a écrit :
> May I ask: > What's the idiomatic way to retrieve values from nested dictionaries? > > (((dict1 at: 'key1') at: 'key2') at: 'key3') > > Are all the brackets really necessary? > > BR Mike Hi, To know if brackets are necessary you can use the "Format" option in your method. Right click -> format or cmd/alt/ctrl + shift + f In this case you can just write: ((dict1 at: 'key1') at: 'key2') at: 'key3'. -- Cyril Ferlicot https://ferlicot.fr http://www.synectique.eu 2 rue Jacques Prévert 01, 59650 Villeneuve d'ascq France signature.asc (836 bytes) Download Attachment |
Tx for advice. P.S.: I got nested dictionaries after JSON API call at wunderground weather API. To see all the response in Pharo inspector "live" is really great :-) BR Mike On Mon, Apr 24, 2017 at 7:51 PM, Cyril Ferlicot D. <[hidden email]> wrote:
|
In reply to this post by Juraj Kubelka
For these use cases it would be nice to have some sort of syntax sugar
as with the cascade operator, but with a chaining operator instead. The chaining operator would send the message to the result of the previous statement instead of the original receiver as in the semicolon cascade operator (;). E.g. dict1 at: 'key1' : at: 'key2' : at: 'key3' . I selected the colon character in the lack of non-message related characters. It's only a daydream and nothing that I found very often needing, except for cases like the mentioned in this thread, extracting a deeply nested value from a JSON object tree/dictionary. ps: use the extra parenthesis, they're not that many. :) Regards! Esteban A. Maringolo 2017-04-24 14:48 GMT-03:00 Juraj Kubelka <[hidden email]>: > >> On Apr 24, 2017, at 14:42, Markus Böhm <[hidden email]> wrote: >> >> May I ask: >> What's the idiomatic way to retrieve values from nested dictionaries? >> >> (((dict1 at: 'key1') at: 'key2') at: 'key3') >> >> Are all the brackets really necessary? > > I think so, without the parenthesis, it is interpreted as one message at:at:at: > > If you use it a lot, you may want to convert the dictionary structure into domain objects. > > Juraj > >> >> BR Mike > > |
In reply to this post by Juraj Kubelka
Maybe we could introduce `@` message, so one can chain them and then even execute keyword without parenthesis
Dictionary>>@ aKey ^ at: aKey dict @ 'key1' @ 'key2' @ 'key3' dict @ 'key1' @ 'key2' @ 'key3' select: [ :each | ... ] I'm always adding this when hacking around, maybe we could have it in Pharo. Peter On Mon, Apr 24, 2017 at 02:48:48PM -0300, Juraj Kubelka wrote: > > > On Apr 24, 2017, at 14:42, Markus Böhm <[hidden email]> wrote: > > > > May I ask: > > What's the idiomatic way to retrieve values from nested dictionaries? > > > > (((dict1 at: 'key1') at: 'key2') at: 'key3') > > > > Are all the brackets really necessary? > > I think so, without the parenthesis, it is interpreted as one message at:at:at: > > If you use it a lot, you may want to convert the dictionary structure into domain objects. > > Juraj > > > > > BR Mike > > |
In reply to this post by Markus Böhm-2
If you are using NeoJSON you might want to take a look at the
NeoJSONObject class. It's basically a Dictionary with "JavaScript" behavior. I.e. you can simply use messages to access keys and non existing keys return nil. Your example can thus be written as: val := dict1 key1 key2 key3. When using NeoJSON you can simply configure your Mapper (Reader/Writer) to use NeoJSONObject using #mapClass: CU, Udo On 24/04/2017 20:04, Markus Böhm wrote: > Tx for advice. > > P.S.: I got nested dictionaries after JSON API call at wunderground > weather API. To see all the response in Pharo inspector "live" is really > great :-) > > BR Mike > > > On Mon, Apr 24, 2017 at 7:51 PM, Cyril Ferlicot D. > <[hidden email] > <mailto:[hidden email]>> wrote: > > Le 24/04/2017 à 19:42, Markus Böhm a écrit : > > May I ask: > > What's the idiomatic way to retrieve values from nested dictionaries? > > > > (((dict1 at: 'key1') at: 'key2') at: 'key3') > > > > Are all the brackets really necessary? > > > > BR Mike > > Hi, > > To know if brackets are necessary you can use the "Format" option in > your method. > > Right click -> format > > or cmd/alt/ctrl + shift + f > > In this case you can just write: > > ((dict1 at: 'key1') at: 'key2') at: 'key3'. > > > > -- > Cyril Ferlicot > https://ferlicot.fr > > http://www.synectique.eu > 2 rue Jacques Prévert 01, > 59650 Villeneuve d'ascq France > > |
On 04/24/2017 11:16 AM, Esteban A. Maringolo wrote:> For these use cases
it would be nice to have some sort of syntax sugar > as with the cascade operator, but with a chaining operator instead. This doesn't even require syntactic sugar, just objects, and this is a more general problem even with a back to back chain of select/detect/reject style things. I solved this for myself years ago by introducing what I call a pipe (nod to unix) allowing me to chain calls in a pipeline without all the parens with each call acting on the result value of the last call. Trivially implemented using #doesNotUnderstand: and the cascade operator. ^ dict1 asPipe at: 'key1'; at: 'key2'; at: 'key3'. Anytime I have a bunch of back to back calls that would require a lot of parens, I just create a pipe... maxRoomsAvailable ^self findBlocks asPipe select: [ :e | e blockDate between: actualCheckInDate and: actualCheckInDate + (nights - 1) days ]; detectMin: [ :e | e quantityAvailable ]; quantityAvailable The simplest implementation is... Object>>asPipe ^ SPipe with: self Object subclass: #SPipe instanceVariableNames: 'value' classVariableNames: '' poolDictionaries: '' category: 'PharoExtensions' privateValue: anObject value := anObject yourself ^ value yourself doesNotUnderstand: aMessage ^ value := value perform: aMessage selector withArguments: aMessage arguments SPipe class>>with: anObject ^ (self new) privateValue: anObject; yourself -- Ramon Leon |
2017-04-24 16:10 GMT-03:00 Ramon Leon <[hidden email]>:
> On 04/24/2017 11:16 AM, Esteban A. Maringolo wrote:> >> For these use cases it >> would be nice to have some sort of syntax sugar >> as with the cascade operator, but with a chaining operator instead. > This doesn't even require syntactic sugar, just objects, and this is a more > general problem even with a back to back chain of select/detect/reject style > things. I solved this for myself years ago by introducing what I call a pipe > (nod to unix) allowing me to chain calls in a pipeline without all the > parens with each call acting on the result value of the last call. Trivially > implemented using #doesNotUnderstand: and the cascade operator. > > ^ dict1 asPipe at: 'key1'; at: 'key2'; at: 'key3'. > > Anytime I have a bunch of back to back calls that would require a lot of > parens, I just create a pipe... > > maxRoomsAvailable > ^self findBlocks asPipe > select: [ :e | e blockDate between: actualCheckInDate and: > actualCheckInDate + (nights - 1) days ]; > detectMin: [ :e | e quantityAvailable ]; > quantityAvailable Very neat implementation. I think this simple class could come as part of the base image :) Esteban A. Maringolo |
In reply to this post by Udo Schneider
Tx, I tried Your proposal. Just as an example, it works: (ZnClient new url: 'http://api.wunderground.com/ contentReader: [ :entity | (NeoJSONReader on: entity readStream) mapClass: NeoJSONObject; propertyNamesAsSymbols: true; next ]; get ) hourly_forecast collect: [:e | e FCTTIME hour_padded asInteger ]
P.S.: Editor in Playground shows NeoJSONObject keys in red color? Am 24.04.2017 9:00 nachm. schrieb "Udo Schneider" <[hidden email]>: If you are using NeoJSON you might want to take a look at the NeoJSONObject class. It's basically a Dictionary with "JavaScript" behavior. |
2017-04-25 8:49 GMT-03:00 Markus Böhm <[hidden email]>:
> Tx, I tried Your proposal. Just as an example, it works: > P.S.: Editor in Playground shows NeoJSONObject keys in red color? It's highlighted in red because for the playground the keys are selectors not implemented by any class in the image. The key in the Playground is not such, only a trick of NeoJSONObject using Smalltalk's #doesNotUnderstand: mechanism to map selectors to keys. Regards! Esteban A. Maringolo |
JsonObject has the doesNotUnderstand: trick too.
|
In reply to this post by Markus Böhm-2
Browsing in Pharo, I found that Dictionary has a subclass KeyedTree, which is in effect a set of nested dictionaries. Retrieval is by quoting a path, which is simply an array of keys. So in your case it would read: dict1 atPath: #(’key1’ ‘key2’ ‘key3’). This might be more efficient than repeated use of the DNU mechanism. It is not clear (to me, at least) how to construct the nested dictionaries as a KeyedTree in the first place, but this might be an alternative approach. Hope this helps Peter Kenny From: Pharo-users [mailto:[hidden email]] On Behalf Of Markus Böhm May I ask: What's the idiomatic way to retrieve values from nested dictionaries? (((dict1 at: 'key1') at: 'key2') at: 'key3') Are all the brackets really necessary? BR Mike |
> On 26 Apr 2017, at 01:01, PBKResearch <[hidden email]> wrote:
> > Browsing in Pharo, I found that Dictionary has a subclass KeyedTree, which is in effect a set of nested dictionaries. Retrieval is by quoting a path, which is simply an array of keys. So in your case it would read: > dict1 atPath: #(’key1’ ‘key2’ ‘key3’). > This might be more efficient than repeated use of the DNU mechanism. It is not clear (to me, at least) how to construct the nested dictionaries as a KeyedTree in the first place, but this might be an alternative approach. I saw this too and I thought it was interesting, hence I added it to NeoJSONObject. Name: Neo-JSON-Core-SvenVanCaekenberghe.40 Author: SvenVanCaekenberghe Time: 26 April 2017, 4:35:49.433269 pm UUID: c336587e-740a-0d00-b51a-dacd0088e41c Ancestors: Neo-JSON-Core-SvenVanCaekenberghe.39 Name: Neo-JSON-Tests-SvenVanCaekenberghe.38 Author: SvenVanCaekenberghe Time: 26 April 2017, 4:36:04.583272 pm UUID: 73623f7f-740a-0d00-b51b-f4000088e41c Ancestors: Neo-JSON-Tests-SvenVanCaekenberghe.37 From the class comment: Additionally, I support path access for nested instances of me, using #atPath: and #atPath:put: The first is special because it returns nil as soon as a key is missing. The second is special because it creates extra levels (instances of me) as needed to follow the path of keys. NeoJSONObject new atPath: #(one two three) put: 42; yourself. NeoJSONObject new atPath: #(one two three) put: 42; atPath: #(one two three). For the examples given above, the actual JSON looks like this: {"one":{"two":{"three":42}}} Sven > Hope this helps > > Peter Kenny > > From: Pharo-users [mailto:[hidden email]] On Behalf Of Markus Böhm > Sent: 24 April 2017 18:42 > To: [hidden email] > Subject: [Pharo-users] Hot to retrieve values from Nested Dictionaries > > May I ask: > What's the idiomatic way to retrieve values from nested dictionaries? > > (((dict1 at: 'key1') at: 'key2') at: 'key3') > > Are all the brackets really necessary? > > BR Mike |
Free forum by Nabble | Edit this page |