Nested dicts (to write and to query, that is the question)

Rodrigo's icon

So I've been dict-ing it on up, all over the place in my patch(es), and there are a couple of things that seem a bit weird to me, so I suspect there are easier ways to do this.

The first one is that I want to write nested dicts, but with arbitrary names, or more specifically, arbitrary amounts. I'm using [counter] to generate keys and creating lots of nested dicts, all with different contents/settings.

A structure like this:

{
    "1" :     {
        "some" : "one",
        "thing" : "two",
        "else" : "three"
    }

}

As much as possible I've been using the dict.objects, so I'm using dict.pack at the top leve to generate what will become the nested dict, but then in order to create a dynamic nested dict name, dict.pack doesn't appear to work. So I'm using a [prepend] with a [set append $1] going in to it. This works, but feels like an awful workaround. (labelled/clear example of this in the code quoted below)

Is there a better (native dict.object) way of adding nested dicts with arbitrary/names without explicitely named [dict.pack insert_name_here:] objects?

SECONDly, once I have a nested dict structure set up, is there a simple way of querying for a specific 'value' at a certain hierarchy depth?

For example, if I have a dict that looks like this:

{
    "first" :     {
        "some" : 1,
        "thing" : 6,
        "else" : 3
    }
,
    "second" :     {
        "some" : 8,
        "thing" : 5,
        "else" : 2
    }
,
    "third" :     {
        "some" : 7,
        "thing" : 4,
        "else" : "9
    }

}

How do I specifically query for the value '8' for example? Now I can 'getkeys', then use that to cycle through the keys, then use that to cycle through the keys etc... Now this works, but it's suuuper clunky, not to mention if I want to query through a dict for all the values to figure out the order of them, I have to loop through the whole process looking for each key specifically (like sorting algorithm style).

Is there a way to query for a specific value through arbitrary nested keys (so can't "get first::some").

Max Patch
Copy patch and select New From Clipboard in Max.

p.s. this thread was super useful, as was this blog post.

broc's icon

Obviously dict has cons and pros. So for complex and flexible data management I'm often using a combination of dicts and colls (including temporary conversions between them).

Rodrigo's icon

I'm doing something similar, particularly when it comes to large data sets, as [dict.iter] is SIGNIFICANTLY slower than 'dump'-ing a coll. But the main issue here is that I want to be able to easily pattrize/recall dicts inside a M4L device.

That being said, I did find a workaround for the [prepend append] problem.

If you use a @named dict.pack (i.e. [dict.pack @name ---CurrentlyLoadedCorpora]), then you can send it a message of 'keys whatever' and it works fine. If you do the same without the @name attribute, then it generates a generic foo::bar key/value pair, which is annoying.

stkr's icon

yeah i have been burned by that @named only working on dict.pack if explicitly declared first. it must be a bug. i have lazily not reported that one, sorry. once done though, it solves all your issues, no? i use it to dynamically name nested dicts when structure is not known beforehand. i guess improving dict.iter / dumping would be very high on all our future request lists for max 8 :-)

Rodrigo's icon

Actually as I dicovered, the @name thing still does create a generic "foo:bar" entry, but only sometimes (possibly bug?). Specifically in my patch I noticed that the named [dict.pack @name histogram] works just fine, creating an empty dictionary on startup, but having two [dict.pack @name analysis] creates a foo:bar entry on startup. Took me a while to troubleshoot/find that as deleting just one didn't solve it, and the [dict.pack]s arent receiving any messaging on loadup.

You would presume that the dict.objects would take messages ala pack/join/group/etc...

On a real positive note, I've managed to totally get all the dict stuff I want working! (including recalling/reloading all data when the patch is loaded) There are lots of workaround all over the place, given the kind of things I want to do with dicts, but it's working!