digitalmars.D.learn - Associative array key order
- Daniel Kozak (10/10) Jul 31 2013 D:
- Daniel Kozak (11/11) Jul 31 2013 D:
- Dicebot (9/10) Jul 31 2013 I doubt it. This snippet suggests that AA's in PHP are not simply
- Daniel Kozak (3/14) Jul 31 2013 Thanks I will use plain array, it is not perfect but better than
- Andrej Mitrovic (3/5) Jul 31 2013 For some reason this (unordered keys) wasn't documented on the
- Daniel Kozak (6/15) Aug 22 2013 I implemented my own OrderedAA type, which is able to preserve
- monarch_dodra (3/19) Aug 22 2013 Nice to hear. Perhaps you could share the implementation with us?
- Daniel Kozak (3/26) Aug 22 2013 Yes, it should not be a problem. This evening I should have some
- Daniel Kozak (2/25) Aug 23 2013
- H. S. Teoh (11/12) Aug 23 2013 [...]
- bearophile (5/6) Aug 23 2013 On this subject, I added this request to Bugzilla:
- bearophile (4/6) Aug 23 2013 Your answer was really too much short, so I have asked you a
- Daniel Kozak (4/20) Aug 23 2013 When I do some cleanups, I find some bugs and after fixing them,
- Sean Kelly (16/20) Aug 23 2013 and do additionally track insertion order (or use some similar trick). =
- H. S. Teoh (14/36) Aug 23 2013 In http://d.puremagic.com/issues/show_bug.cgi?id=10733 bearophile and I
- bearophile (15/16) Jul 31 2013 D associative arrays are based on hashing, so they do not keep
- bearophile (23/25) Jul 31 2013 Perhaps you need a better explanation for that. Let's say your
- Ary Borenszweig (11/17) Jul 31 2013 However in Ruby 1.9 they are ordered.
- H. S. Teoh (6/26) Jul 31 2013 [...]
- Ary Borenszweig (3/27) Jul 31 2013 Sorry, I meant doubly-linked list. But yeah, two pointers seem now too
- bearophile (25/34) Jul 31 2013 If it's a singly linked list how do you remove a key from the
- H. S. Teoh (6/21) Jul 31 2013 AA's in D are unordered. If you want a specific order, you should use an
D: foreach(key, val; ["query" : 1, "count" : 2]) writeln(key); // print count query foreach(key, val; ["count" : 1, "query" : 2]) writeln(key); // print count query too PHP: foreach(["query" => 1,"count"=>2] as $key => $val) echo $key; // print query count foreach(["count" => 1,"query"=>2] as $key => $val) echo $key; is there a way for AA to change order?
Jul 31 2013
D: foreach(key, val; ["query" : 1, "count" : 2]) writeln(key); // print count query foreach(key, val; ["count" : 1, "query" : 2]) writeln(key); // print count query too PHP: foreach(["query" => 1,"count"=>2] as $key => $val) echo $key; // print query count foreach(["count" => 1,"query"=>2] as $key => $val) echo $key; // print count query is there a way for AA to behave same as PHP?
Jul 31 2013
On Wednesday, 31 July 2013 at 14:43:21 UTC, Daniel Kozak wrote:is there a way for AA to behave same as PHP?I doubt it. This snippet suggests that AA's in PHP are not simply AA's and do additionally track insertion order (or use some similar trick). Data in associative arrays is organized in a way that allows fast key lookup and iterating in an original order requires tracking extra state. Contrary to PHP, D does care about performance so I see no way this can happen automatically. There is a good chance that if you rely on key order, you don't really need an AA but plain array of key-value tuples instead.
Jul 31 2013
On Wednesday, 31 July 2013 at 14:55:55 UTC, Dicebot wrote:On Wednesday, 31 July 2013 at 14:43:21 UTC, Daniel Kozak wrote:Thanks I will use plain array, it is not perfect but better than nothing :)is there a way for AA to behave same as PHP?I doubt it. This snippet suggests that AA's in PHP are not simply AA's and do additionally track insertion order (or use some similar trick). Data in associative arrays is organized in a way that allows fast key lookup and iterating in an original order requires tracking extra state. Contrary to PHP, D does care about performance so I see no way this can happen automatically. There is a good chance that if you rely on key order, you don't really need an AA but plain array of key-value tuples instead.
Jul 31 2013
On Wednesday, 31 July 2013 at 15:00:34 UTC, Daniel Kozak wrote:Thanks I will use plain array, it is not perfect but better than nothing :)For some reason this (unordered keys) wasn't documented on the website, but it will be soon.
Jul 31 2013
On Wednesday, 31 July 2013 at 14:55:55 UTC, Dicebot wrote:On Wednesday, 31 July 2013 at 14:43:21 UTC, Daniel Kozak wrote:I implemented my own OrderedAA type, which is able to preserve insert order and is a little faster and take less memory(30%) then the builtin one :-). But definitly there will be some cases where my own implementation doesn't beat the builtin one.is there a way for AA to behave same as PHP?I doubt it. This snippet suggests that AA's in PHP are not simply AA's and do additionally track insertion order (or use some similar trick). Data in associative arrays is organized in a way that allows fast key lookup and iterating in an original order requires tracking extra state. Contrary to PHP, D does care about performance so I see no way this can happen automatically.
Aug 22 2013
On Thursday, 22 August 2013 at 07:59:05 UTC, Daniel Kozak wrote:On Wednesday, 31 July 2013 at 14:55:55 UTC, Dicebot wrote:Nice to hear. Perhaps you could share the implementation with us? Even if its not perfect, I'm curious to know how you went at it.On Wednesday, 31 July 2013 at 14:43:21 UTC, Daniel Kozak wrote:I implemented my own OrderedAA type, which is able to preserve insert order and is a little faster and take less memory(30%) then the builtin one :-). But definitly there will be some cases where my own implementation doesn't beat the builtin one.is there a way for AA to behave same as PHP?I doubt it. This snippet suggests that AA's in PHP are not simply AA's and do additionally track insertion order (or use some similar trick). Data in associative arrays is organized in a way that allows fast key lookup and iterating in an original order requires tracking extra state. Contrary to PHP, D does care about performance so I see no way this can happen automatically.
Aug 22 2013
On Thursday, 22 August 2013 at 08:41:13 UTC, monarch_dodra wrote:On Thursday, 22 August 2013 at 07:59:05 UTC, Daniel Kozak wrote:Yes, it should not be a problem. This evening I should have some more spare time. So I do some cleanups and push it somewhere.On Wednesday, 31 July 2013 at 14:55:55 UTC, Dicebot wrote:Nice to hear. Perhaps you could share the implementation with us? Even if its not perfect, I'm curious to know how you went at it.On Wednesday, 31 July 2013 at 14:43:21 UTC, Daniel Kozak wrote:I implemented my own OrderedAA type, which is able to preserve insert order and is a little faster and take less memory(30%) then the builtin one :-). But definitly there will be some cases where my own implementation doesn't beat the builtin one.is there a way for AA to behave same as PHP?I doubt it. This snippet suggests that AA's in PHP are not simply AA's and do additionally track insertion order (or use some similar trick). Data in associative arrays is organized in a way that allows fast key lookup and iterating in an original order requires tracking extra state. Contrary to PHP, D does care about performance so I see no way this can happen automatically.
Aug 22 2013
https://github.com/Kozzi11/Trash/blob/master/util/orderedaa.d On Thursday, 22 August 2013 at 08:41:13 UTC, monarch_dodra wrote:On Thursday, 22 August 2013 at 07:59:05 UTC, Daniel Kozak wrote:On Wednesday, 31 July 2013 at 14:55:55 UTC, Dicebot wrote:Nice to hear. Perhaps you could share the implementation with us? Even if its not perfect, I'm curious to know how you went at it.On Wednesday, 31 July 2013 at 14:43:21 UTC, Daniel Kozak wrote:I implemented my own OrderedAA type, which is able to preserve insert order and is a little faster and take less memory(30%) then the builtin one :-). But definitly there will be some cases where my own implementation doesn't beat the builtin one.is there a way for AA to behave same as PHP?I doubt it. This snippet suggests that AA's in PHP are not simply AA's and do additionally track insertion order (or use some similar trick). Data in associative arrays is organized in a way that allows fast key lookup and iterating in an original order requires tracking extra state. Contrary to PHP, D does care about performance so I see no way this can happen automatically.
Aug 23 2013
On Fri, Aug 23, 2013 at 01:54:27PM +0200, Daniel Kozak wrote:https://github.com/Kozzi11/Trash/blob/master/util/orderedaa.d[...] Neat! Is a doubly-linked list really necessary for the hash buckets? You could save on some memory & improve performance slightly if you use a singly-linked list for the buckets, but still keep the left/right pointers for retaining insertion order. It will also simplify your code a bit. T -- If Java had true garbage collection, most programs would delete themselves upon execution. -- Robert Sewell
Aug 23 2013
H. S. Teoh:...On this subject, I added this request to Bugzilla: http://d.puremagic.com/issues/show_bug.cgi?id=10733 Bye, bearophile
Aug 23 2013
H. S. Teoh:Your answer was really too much short, so I have asked you a question in that enhancement request :-) Bye, bearophile...
Aug 23 2013
When I do some cleanups, I find some bugs and after fixing them, my own OrderedAA implementation does not beat builtin hash anymore :(. But speed is still really near to builtin AA's. On Thursday, 22 August 2013 at 07:59:05 UTC, Daniel Kozak wrote:On Wednesday, 31 July 2013 at 14:55:55 UTC, Dicebot wrote:On Wednesday, 31 July 2013 at 14:43:21 UTC, Daniel Kozak wrote:I implemented my own OrderedAA type, which is able to preserve insert order and is a little faster and take less memory(30%) then the builtin one :-). But definitly there will be some cases where my own implementation doesn't beat the builtin one.is there a way for AA to behave same as PHP?I doubt it. This snippet suggests that AA's in PHP are not simply AA's and do additionally track insertion order (or use some similar trick). Data in associative arrays is organized in a way that allows fast key lookup and iterating in an original order requires tracking extra state. Contrary to PHP, D does care about performance so I see no way this can happen automatically.
Aug 23 2013
On Jul 31, 2013, at 7:55 AM, Dicebot <public dicebot.lv> wrote:On Wednesday, 31 July 2013 at 14:43:21 UTC, Daniel Kozak wrote:and do additionally track insertion order (or use some similar trick). = Data in associative arrays is organized in a way that allows fast key = lookup and iterating in an original order requires tracking extra state. = Contrary to PHP, D does care about performance so I see no way this can = happen automatically. This seems more likely to be a library type. I have something like this = that I use very frequently at work where the behavior is pluggable, so = it can be used as a cache that automatically does LIFO/FIFO eviction = according to an age window, number of entries, etc. Or none of those if = all you want is a plain old hashtable. It's not a tremendous amount of = work to adapt an existing implementation to work this way. The only = annoying bit I ran into (at least with C++) is that the symbol lookup = rules pretty much prevent overrides of existing functions to be mixed in = via the policies. Does alias this work around this problem in D? I've = never tried.=is there a way for AA to behave same as PHP?=20 I doubt it. This snippet suggests that AA's in PHP are not simply AA's =
Aug 23 2013
On Fri, Aug 23, 2013 at 11:22:47AM -0700, Sean Kelly wrote:On Jul 31, 2013, at 7:55 AM, Dicebot <public dicebot.lv> wrote:In http://d.puremagic.com/issues/show_bug.cgi?id=10733 bearophile and I discussed code reuse between the current AA and an ordered AA implementation. It appears that a more fundamental structure is the Set, where the key is the value. An AA can be implemented in terms of a Set, by making the set element a struct containing a key and value field, with a custom toHash() and opCmp() that only hashes/compares the key part. By adding a pair of pointers to this customized set element, we can make an ordered AA in terms of Set. Plus, a Set is something that's very useful on its own as well. T -- Береги платье снову, а здоровье смолоду.On Wednesday, 31 July 2013 at 14:43:21 UTC, Daniel Kozak wrote:This seems more likely to be a library type. I have something like this that I use very frequently at work where the behavior is pluggable, so it can be used as a cache that automatically does LIFO/FIFO eviction according to an age window, number of entries, etc. Or none of those if all you want is a plain old hashtable. It's not a tremendous amount of work to adapt an existing implementation to work this way. The only annoying bit I ran into (at least with C++) is that the symbol lookup rules pretty much prevent overrides of existing functions to be mixed in via the policies. Does alias this work around this problem in D? I've never tried.is there a way for AA to behave same as PHP?I doubt it. This snippet suggests that AA's in PHP are not simply AA's and do additionally track insertion order (or use some similar trick). Data in associative arrays is organized in a way that allows fast key lookup and iterating in an original order requires tracking extra state. Contrary to PHP, D does care about performance so I see no way this can happen automatically.
Aug 23 2013
Daniel Kozak:is there a way for AA to behave same as PHP?D associative arrays are based on hashing, so they do not keep the order of the items. This is true in Python too. The Python standard library has a hash-based ordered dict that keeps the insertion order of the keys. There is no such data structure in Phobos. You could write one yourself (wrapping an associative array and using a linked list. I remember there is a trick to find the address of a D associative array key given its value address, but I don't remember it and it's not portable). An alternative solution is to use the Phobos AVL-based tree as an associative array, but it's less convenient and the search complexity is logarithmic instead of constant in the average case. Bye, bearophile
Jul 31 2013
I remember there is a trick to find the address of a D associative array key given its value address,Perhaps you need a better explanation for that. Let's say your data structure is: final class OrderedAA(TK, TV) { struct MV { TV item; MV* pred, succ; } private MV[TK] data; ... } it's a wrapper to a built-in associative array. Each value is a struct that beside the original value contains a pointer to the precedent and successive MV, in a doubly linked list. The member functions of OrderedAA that add or remove items from the associative array manage the linked list of values. The iteration is a range that follows the linked list. But this way you only scan the values... To also scan keys or key-val pairs you have to find the pointer to the key. Maybe it's worth adding in Bugzilla an ehnancement request for a portable way to find that pointer... to implement a hash-based ordered associative array in library code. Bye, bearophile
Jul 31 2013
On 7/31/13 12:05 PM, bearophile wrote:Daniel Kozak:However in Ruby 1.9 they are ordered. You only need to store in each bucket entry a pointer to the next bucket. Then traversing the hash is super fast (just follow the links) while preserving insertion order. Accessing by key still uses the buckets and entries (if that's how AAs are implemented in D). I don't think adding a pointer to each bucket entry hurts performance that much, and having traversal by insertion order is pretty common (in my opinion). To see a sample code for this: https://github.com/manastech/crystal/blob/master/std/hash.cr#L28is there a way for AA to behave same as PHP?D associative arrays are based on hashing, so they do not keep the order of the items. This is true in Python too. The Python standard library has a hash-based ordered dict that keeps the insertion order of the keys. There is no such data structure in Phobos.
Jul 31 2013
On Wed, Jul 31, 2013 at 12:51:25PM -0300, Ary Borenszweig wrote:On 7/31/13 12:05 PM, bearophile wrote:[...] It does. What do you do when you delete entries? T -- Windows 95 was a joke, and Windows 98 was the punchline.Daniel Kozak:However in Ruby 1.9 they are ordered. You only need to store in each bucket entry a pointer to the next bucket. Then traversing the hash is super fast (just follow the links) while preserving insertion order. Accessing by key still uses the buckets and entries (if that's how AAs are implemented in D). I don't think adding a pointer to each bucket entry hurts performance that much, and having traversal by insertion order is pretty common (in my opinion).is there a way for AA to behave same as PHP?D associative arrays are based on hashing, so they do not keep the order of the items. This is true in Python too. The Python standard library has a hash-based ordered dict that keeps the insertion order of the keys. There is no such data structure in Phobos.
Jul 31 2013
On 7/31/13 12:56 PM, H. S. Teoh wrote:On Wed, Jul 31, 2013 at 12:51:25PM -0300, Ary Borenszweig wrote:Sorry, I meant doubly-linked list. But yeah, two pointers seem now too much overhead.On 7/31/13 12:05 PM, bearophile wrote:[...] It does. What do you do when you delete entries? TDaniel Kozak:However in Ruby 1.9 they are ordered. You only need to store in each bucket entry a pointer to the next bucket. Then traversing the hash is super fast (just follow the links) while preserving insertion order. Accessing by key still uses the buckets and entries (if that's how AAs are implemented in D). I don't think adding a pointer to each bucket entry hurts performance that much, and having traversal by insertion order is pretty common (in my opinion).is there a way for AA to behave same as PHP?D associative arrays are based on hashing, so they do not keep the order of the items. This is true in Python too. The Python standard library has a hash-based ordered dict that keeps the insertion order of the keys. There is no such data structure in Phobos.
Jul 31 2013
Ary Borenszweig:However in Ruby 1.9 they are ordered. You only need to store in each bucket entry a pointer to the next bucket. Then traversing the hash is super fast (just follow the links) while preserving insertion order. Accessing by key still uses the buckets and entries (if that's how AAs are implemented in D).If it's a singly linked list how do you remove a key from the associative array keeping the list coherent? How do you know where is the precedent to remove an item from the linked list? Using the 'deleted' tag on AA items is enough to skip the deleted items when you scan the singly linked list, but when you re-use that space I think you mess things up. One way to solve it is to never re-use locations, but this is bad if you want to add and remove many items.I don't think adding a pointer to each bucket entry hurts performance that much, and having traversal by insertion order is pretty common (in my opinion).Python has such data structure in the standard library, and thanks to dynamic typing it's transparently compatible with associative arrays, so when you need it you have it. I have often needed such data structure, but it's not always needed, I need it probably less than 5% of the times. Python uses associative arrays all the time, they must be as fast as possible, so it's a good idea to not add that feature to the standard associative arrays. This is true for the built-in associative arrays too, despite they should be designed for flexibility first and despite D doesn't use associative arrays for basic language purposes, as Python does (symbol lookup for variables!). I have added a small enhancement request to Bugzilla: http://d.puremagic.com/issues/show_bug.cgi?id=10733 Bye, bearophile
Jul 31 2013
On Wed, Jul 31, 2013 at 04:41:14PM +0200, Daniel Kozak wrote:D: foreach(key, val; ["query" : 1, "count" : 2]) writeln(key); // print count query foreach(key, val; ["count" : 1, "query" : 2]) writeln(key); // print count query too PHP: foreach(["query" => 1,"count"=>2] as $key => $val) echo $key; // print query count foreach(["count" => 1,"query"=>2] as $key => $val) echo $key; is there a way for AA to change order?AA's in D are unordered. If you want a specific order, you should use an array, or sort the AA keys before looping over them. T -- I see that you JS got Bach.
Jul 31 2013