digitalmars.D.learn - Find if keys are in two dimensional associative array
- Michal Minich (14/14) Jan 17 2010 if one has double indexed aa, how to find that it contains value under
- Mike Wey (10/24) Jan 17 2010 This should work.
- Michal Minich (4/14) Jan 17 2010 if 'a' is not there then "aa['a'] will either return null, or exception
- bearophile (5/6) Jan 17 2010 Is something like this good for you (but I don't remember if Tuples defi...
- Michal Minich (9/17) Jan 17 2010 if I have more lookups based on int than on char like:
- bearophile (4/6) Jan 17 2010 In D the built in AAs require an equality test and/or cmp, plus opHash. ...
- Michal Minich (5/10) Jan 17 2010 Why should AAs require opCmp. What if object is not logically sortable,
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (13/19) Jan 17 2010 AAs require all three for classes: opEquals, opCmp, and toHash. Further,...
- bearophile (4/5) Jan 18 2010 I have already given the answer, the hash collisions are resolved with a...
- Simen kjaeraas (30/31) Jan 17 2010 As far as I know, there is no built-in way. A more general solution than...
- Michal Minich (11/47) Jan 17 2010 This is great! I was thinking such generic template would be good, but I...
- Simen kjaeraas (54/64) Jan 17 2010 Thank you. I have now improved the code to also work for normal arrays:
- BCS (5/26) Jan 17 2010 That's how I'd do it, more or less. However I'd skip the function (or go...
- Jesse Phillips (4/18) Jan 18 2010 Don't know if this would have any affect on what you want, but there is
- Michal Minich (3/8) Jan 19 2010 Thank you, but it is some other issue. I posted enhacement request alrea...
if one has double indexed aa, how to find that it contains value under keys 'a' and 123 float[int][char] aa; aa['a'][123] = 4.56; I had to make following helper function. Is there more elegant way / built in into D? float* isIn = doubleIn(123, 'a'); float* doubleIn (int i, char ch) { float[int]* first = ch in aa; if (first is null) return null; else return i in *first; }
Jan 17 2010
On 01/17/2010 01:23 PM, Michal Minich wrote:if one has double indexed aa, how to find that it contains value under keys 'a' and 123 float[int][char] aa; aa['a'][123] = 4.56; I had to make following helper function. Is there more elegant way / built in into D? float* isIn = doubleIn(123, 'a'); float* doubleIn (int i, char ch) { float[int]* first = ch in aa; if (first is null) return null; else return i in *first; }This should work. float[int][char] aa; aa['a'][123] = 4.56; if ( 123 in aa['a'] ) writeln(true); else writeln(false); -- Mike Wey
Jan 17 2010
On Sun, 17 Jan 2010 15:08:08 +0100, Mike Wey wrote:This should work. float[int][char] aa; aa['a'][123] = 4.56; if ( 123 in aa['a'] ) writeln(true); else writeln(false);if 'a' is not there then "aa['a'] will either return null, or exception (I don't know exactly). This is not good in any case, because then asking "123 in null" will crash always...
Jan 17 2010
Michal Minich:float[int][char] aa;Is something like this good for you (but I don't remember if Tuples define a toHash)? float[Tuple!(char, int)] aa; Bye, bearophile
Jan 17 2010
On Sun, 17 Jan 2010 09:11:06 -0500, bearophile wrote:Michal Minich:if I have more lookups based on int than on char like: tmp = ch in aa; foreach ... i in tmp then I think this would be more effective than always searching by both values in tuple. Anyway the tuple is struct. I think struct equality is defined by equality of all fields, then it should work in AA...float[int][char] aa;Is something like this good for you (but I don't remember if Tuples define a toHash)? float[Tuple!(char, int)] aa; Bye, bearophile
Jan 17 2010
Michal Minich:Anyway the tuple is struct. I think struct equality is defined by equality of all fields, then it should work in AA...In D the built in AAs require an equality test and/or cmp, plus opHash. (The collisions are resolved with an ordered search tree (maybe AVL, I don't remember, probably not a ternary tree)). Normal structs don't define all that. I don't remember if Tuple of D2 define all that. See the docs. (My Record struct can be used just fine as AA keys). Bye, bearophile
Jan 17 2010
On Sun, 17 Jan 2010 11:28:49 -0500, bearophile wrote:In D the built in AAs require an equality test and/or cmp, plus opHash. (The collisions are resolved with an ordered search tree (maybe AVL, I don't remember, probably not a ternary tree)). Normal structs don't define all that. I don't remember if Tuple of D2 define all that. See the docs. (My Record struct can be used just fine as AA keys).Why should AAs require opCmp. What if object is not logically sortable, (like Guid, DbConnection, ...). Equality & Hash should be enough... Is the opCmp here to optimize lookup? Because opCmp may be quite slow, which may affect appending performance...
Jan 17 2010
Michal Minich wrote:On Sun, 17 Jan 2010 11:28:49 -0500, bearophile wrote:AAs require all three for classes: opEquals, opCmp, and toHash. Further, opEquals and opCmp must be consistent: when opEquals returns true, opCmp must return 0, and when opCmp returns non-zero, opEquals must return false. toHash is optional for structs.In D the built in AAs require an equality test and/or cmp, plus opHash.Why should AAs require opCmp. What if object is not logically sortable, (like Guid, DbConnection, ...). Equality & Hash should be enough... Is the opCmp here to optimize lookup? Because opCmp may be quite slow, which may affect appending performance...I don't know the answer, but the spec says so at http://digitalmars.com/d/2.0/arrays.html <quote> The implementation may use either opEquals or opCmp or both. Care should be taken so that the results of opEquals and opCmp are consistent with each other when the class objects are the same or not. </quote> Ali
Jan 17 2010
Ali Çehreli:I don't know the answer, but the spec says so atI have already given the answer, the hash collisions are resolved with an ordered search tree. Bye, bearophile
Jan 18 2010
Michal Minich <michal.minich gmail.com> wrote:Is there more elegant way / built in into D?As far as I know, there is no built-in way. A more general solution than yours can be created with templates, however: template elementTypeOfDepth( T : V[ K ], int depth, V, K ) { static if ( depth == 0 ) { alias V elementTypeOfDepth; } else { alias elementTypeOfDepth!( V, depth -1 ) elementTypeOfDepth; } } elementTypeOfDepth!( T, U.length )* isIn( T : V[ K ], V, K, U... )( T arr, K key, U index ) { auto p = key in arr; static if ( U.length > 0 ) { if ( p ) { return isIn( *p, index ); } else { return null; } } else { return p; } } Usage: int[char][int][char] foo; if ( isIn( foo, 'a', 3, 'b' ) ) { writeln( "Excelsior!" ); } -- Simen
Jan 17 2010
On Sun, 17 Jan 2010 18:02:00 +0100, Simen kjaeraas wrote:Michal Minich <michal.minich gmail.com> wrote:This is great! I was thinking such generic template would be good, but I did not have need for it right now. This should be definitely posted to bugzilla as enhancement for Phobos, and also for Tango. I was thinking this also may be solved by modification in language: the problem with statement "123 in *('a' in aa)" is that if "('a' in aa')" returns null, then next check will fail: (123 in null) -> null reference error. if D simply check if the second part of InExpression is null, and if yes, return null, otherwise evaluate as is currently done.Is there more elegant way / built in into D?As far as I know, there is no built-in way. A more general solution than yours can be created with templates, however: template elementTypeOfDepth( T : V[ K ], int depth, V, K ) { static if ( depth == 0 ) { alias V elementTypeOfDepth; } else { alias elementTypeOfDepth!( V, depth -1 ) elementTypeOfDepth; } } elementTypeOfDepth!( T, U.length )* isIn( T : V[ K ], V, K, U... )( T arr, K key, U index ) { auto p = key in arr; static if ( U.length > 0 ) { if ( p ) { return isIn( *p, index ); } else { return null; } } else { return p; } } Usage: int[char][int][char] foo; if ( isIn( foo, 'a', 3, 'b' ) ) { writeln( "Excelsior!" ); }
Jan 17 2010
Michal Minich <michal.minich gmail.com> wrote:This is great! I was thinking such generic template would be good, but I did not have need for it right now. This should be definitely posted to bugzilla as enhancement for Phobos, and also for Tango.Thank you. I have now improved the code to also work for normal arrays: template elementTypeOfDepth( T : V[ K ], int depth, V, K ) { static if ( depth == 0 ) { alias V elementTypeOfDepth; } else { alias elementTypeOfDepth!( V, depth -1 ) elementTypeOfDepth; } } template elementTypeOfDepth( T : V[ ], int depth, V ) { static if ( depth == 0 ) { alias V elementTypeOfDepth; } else { alias elementTypeOfDepth!( V, depth -1 ) elementTypeOfDepth; } } elementTypeOfDepth!( T, U.length )* isIn( T : V[ ], V, U... )( T arr, size_t key, U index ) { if ( key < arr.length ) { auto p = arr[ key ]; static if ( U.length > 0 ) { if ( p ) { return isIn( p, index ); } else { return null; } } else { return p; } } else { return null; } } elementTypeOfDepth!( T, U.length )* isIn( T : V[ K ], V, K, U... )( T arr, K key, U index ) { auto p = key in arr; static if ( U.length > 0 ) { if ( p ) { return isIn( *p, index ); } else { return null; } } else { return p; } } Usage: int[char][][int] foo; if ( isIn( foo, 3, 87, 'a' ) ) { writeln( "Excelsior!" ); }I was thinking this also may be solved by modification in language: the problem with statement "123 in *('a' in aa)" is that if "('a' in aa')" returns null, then next check will fail: (123 in null) -> null reference error. if D simply check if the second part of InExpression is null, and if yes, return null, otherwise evaluate as is currently done.This sounds good. Put it in Bugzilla. -- Simen
Jan 17 2010
Hello Michal,if one has double indexed aa, how to find that it contains value under keys 'a' and 123 float[int][char] aa; aa['a'][123] = 4.56; I had to make following helper function. Is there more elegant way / built in into D? float* isIn = doubleIn(123, 'a'); float* doubleIn (int i, char ch) { float[int]* first = ch in aa; if (first is null) return null; else return i in *first; }That's how I'd do it, more or less. However I'd skip the function (or go with the more general case as shown by Simen). float* isIn = null; if(auto a = 'a' in aa) b = 123 in *a;
Jan 17 2010
Michal Minich wrote:if one has double indexed aa, how to find that it contains value under keys 'a' and 123 float[int][char] aa; aa['a'][123] = 4.56; I had to make following helper function. Is there more elegant way / built in into D? float* isIn = doubleIn(123, 'a'); float* doubleIn (int i, char ch) { float[int]* first = ch in aa; if (first is null) return null; else return i in *first; }Don't know if this would have any affect on what you want, but there is this bugzilla: "Associative array of associative arrays gets confused" http://d.puremagic.com/issues/show_bug.cgi?id=3709
Jan 18 2010
Hello Jesse,Don't know if this would have any affect on what you want, but there is this bugzilla: "Associative array of associative arrays gets confused" http://d.puremagic.com/issues/show_bug.cgi?id=3709Thank you, but it is some other issue. I posted enhacement request already http://d.puremagic.com/issues/show_bug.cgi?id=3718
Jan 19 2010