Dictionary access by index

I get a dictionary with a list of IDs and values like:

dict = {
  GUID1=> {...},
  GUID2=> {...},
  GUID3=> {...},
}

The list is sorted by datetime (a field inside the {...}.
I need to read only the last 10 entries. So I tried to get the key array with dict.keys( ) and loop over it. But this key list is not sorted like the dictionary. The keys are GUIDs and that's why  I can't sort by it.
And the dictionary I can only access by key, not by index - or is it possible?

Has anyone an example how to access the dictionary by index - or if it's possible to get the key array in same order like the dictionary.

Many thanks.

  • var x = {"a"=>"x", "b"=>"y"};
    LOG.println(x);
    LOG.println(x.keys());

    ----

    {a=>x, b=>y}
    [a, b]

    so if your WebAPI returns "sorted" by {...} keys() returns "sorted" too

  • Good hint. I only compared the Json response in the browser (RestClient) with the keys() array. Perhaps the wrong order occours in makeWebRequest the it's Json parser. I will check this...

  • I checked now... You are right. The key() method seems to work in right order.
    But the result of makeWebRequest is unsorted. So makeWebRequest is muddle up the data while parsing the http response into a dictionary.
    Any idea how to solve this without an order method on arrays? Loop over the keys array with an own sort algorithm?

  • can you say WebAPI returns sorted json and monkeyc dictionary is sorted different?

  • can you say WebAPI returns sorted json and monkeyc dictionary is sorted different?

    Yes, that's the case.

    Here is the WebAPI response (the first 3 entries):

    {
      "2c00d689-a717-4247-9690-ada885e2cdaa": {
        "id": "2c00d689-a717-4247-9690-ada885e2cdaa",
        "ownerUri": "homey:manager:notifications",
        "dateCreated": "2022-06-30T20:23:46.973Z",
        "excerpt": "Willkommen! Wichtige Benachrichtigungen erscheinen hier, während du Homey nutzt.",
        "icon": null,
        "iconObj": null,
        "priority": "INFORMATIVE",
        "readBy": [],
        "roles": [
          "owner",
          "user"
        ],
        "meta": {}
      },
      "5c9137b0-b86b-44c2-83dc-b341e8b7806e": {
        "id": "5c9137b0-b86b-44c2-83dc-b341e8b7806e",
        "ownerUri": "homey:manager:updates",
        "dateCreated": "2022-06-30T20:27:09.725Z",
        "excerpt": "**Homey** wurde auf die Software-Version **8.0.1** aktualisiert",
        "icon": null,
        "iconObj": null,
        "priority": "INFORMATIVE",
        "readBy": [],
        "roles": [
          "owner",
          "user"
        ],
        "meta": {}
      },
      "127dfc86-11c1-49b9-a5d8-952f7cc4e139": {
        "id": "127dfc86-11c1-49b9-a5d8-952f7cc4e139",
        "ownerUri": "homey:manager:apps",
        "dateCreated": "2022-07-01T21:10:37.972Z",
        "excerpt": "Die App **Test** funktioniert nicht mehr.",
        "icon": null,
        "iconObj": null,
        "priority": "INFORMATIVE",
        "readBy": [],
        "roles": [
          "owner",
          "user"
        ],
        "meta": {}
      },
    ... 


    And the result of makeWebRequest:

    {603d7912-948d-4a82-a746-11c1bee40755=>{dateCreated=>2022-07-22T02:06:56.544Z, iconObj=>null, id=>603d7912-948d-4a82-a746-11c1bee40755, ownerUri=>homey:manager:updates, readBy=>[], icon=>null, excerpt=>Es ist ein Software-Update verfügbar (**8.0.3**)., meta=>{}, priority=>INFORMATIVE, roles=>[owner, user]}, ad0e4205-3a38-4aaa-8272-2edb64bd2585=>{dateCreated=>2022-07-05T21:19:29.543Z, iconObj=>null, id=>ad0e4205-3a38-4aaa-8272-2edb64bd2585, ownerUri=>homey:manager:energy, readBy=>[], icon=>null, excerpt=>Batterie von **Dach Süd** ist jetzt OK., meta=>{}, priority=>INFORMATIVE, roles=>[owner, user]}, 38101bf3-eba8-4148-bf7b-f8b17f311af7=>{dateCreated=>2022-07-03T19:56:16.458Z, iconObj=>null, id=>38101bf3-eba8-4148-bf7b-f8b17f311af7, ownerUri=>homey:manager:flow, readBy=>[], icon=>null, excerpt=>SQL-Error: Invalid type for token 'id' expected 'string' but got 'undefined'., meta=>{}, priority=>INFORMATIVE, roles=>[owner, user]}'
    ...

    Edit:

    Second run:

    {603d7912-948d-4a82-a746-11c1bee40755=>{dateCreated=>2022-07-22T02:06:56.544Z, iconObj=>null, id=>603d7912-948d-4a82-a746-11c1bee40755, ownerUri=>homey:manager:updates, readBy=>[], icon=>null, excerpt=>Es ist ein Software-Update verfügbar (**8.0.3**)., meta=>{}, priority=>INFORMATIVE, roles=>[owner, user]}, ad0e4205-3a38-4aaa-8272-2edb64bd2585=>{dateCreated=>2022-07-05T21:19:29.543Z, iconObj=>null, id=>ad0e4205-3a38-4aaa-8272-2edb64bd2585, ownerUri=>homey:manager:energy, readBy=>[], icon=>null, excerpt=>Batterie von **Dach Süd** ist jetzt OK., meta=>{}, priority=>INFORMATIVE, roles=>[owner, user]}, 38101bf3-eba8-4148-bf7b-f8b17f311af7=>{dateCreated=>2022-07-03T19:56:16.458Z, iconObj=>null, id=>38101bf3-eba8-4148-bf7b-f8b17f311af7, ownerUri=>homey:manager:flow, readBy=>[], icon=>null, excerpt=>SQL-Error: Invalid type for token 'id' expected 'string' but got 'undefined'., meta=>{}, priority=>INFORMATIVE, roles=>[owner, user]},
    ...

    So the order is not random but always the same. But still not in the original order.
  • so

    1. you will guess the order :)

    2. you have to sort data

    But I think there are some limits with amount data in makeWebRequest

    Just Jim is typing so he knows about limits

  • Have you considered using dict.values() and then using an index to go through the results, saving the newest 10?

    Seems using keys() doesn't get you much.

  • What about of limits in data in makeWebRequest? Is any or to the free memory?

    I couldn't download in background for WF more then a few kB but maybe app has more memory.

  • var x = {"a"=>"x", "b"=>"y"};
    LOG.println(x);
    LOG.println(x.keys());

    ----

    {a=>x, b=>y}
    [a, b]

    I don't think that proves anything. For all you know it's a coincidence that in this case, the dictionary data structure has the keys in the same order that they were inserted. Or it's a consequence of the fact that they were added in alphabetical order (and that they're short strings).

    Counter-example:

    var dict = {
       "c" => "3",
       "a" => "1"
    };
    dict.put("b", "2");

    System.println(dict);
    System.println(dict.keys());

    Output:

    {a=>1, b=>2, c=>3}
    [a, b, c]

    Looks like the keys are just in alphabetical order after all, at least in this case. Obviously not in the OPs case. Might have something to do with the hashcodes (although I logged the hashcodes of OP's UUIDs and they're not ascending).

    Also there's this:

    https://developer.garmin.com/connect-iq/api-docs/Toybox/Lang/Dictionary.html

    Due to the nature of hash tables, the order of Dictionary elements are not guaranteed to match the insertion order.

    So it's not like JavaScript where objects follow insertion order (for string keys) since ES2015, or Java's LinkedHashMap which strictly follows insertion order.

  • Have you considered using dict.values() and then using an index to go through the results, saving the newest 10?

    Using an index to determine the "newest 10" won't work if dict.values() isn't ordered in the same way as the original dictionary insert order, or more relevantly, the original order in the JSON response.

    Since the Monkey C docs explicitly say that the order of keys in a Dictionary is not guaranteed to be the same as insertion order (not to mention the fact OP can see dict.values() isn't ordered the same way as the JSON response), I think OP will have to sort the values, ike _psx_ said.