Thread overview | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 17, 2010 Find if keys are in two dimensional associative array | ||||
---|---|---|---|---|
| ||||
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; } |
January 17, 2010 Re: Find if keys are in two dimensional associative array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michal Minich | 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 |
January 17, 2010 Re: Find if keys are in two dimensional associative array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michal Minich | 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
|
January 17, 2010 Re: Find if keys are in two dimensional associative array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Wey | 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...
|
January 17, 2010 Re: Find if keys are in two dimensional associative array | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Sun, 17 Jan 2010 09:11:06 -0500, bearophile wrote:
> 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
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...
|
January 17, 2010 Re: Find if keys are in two dimensional associative array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michal Minich | 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
|
January 17, 2010 Re: Find if keys are in two dimensional associative array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michal Minich | 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 |
January 17, 2010 Re: Find if keys are in two dimensional associative array | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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...
|
January 17, 2010 Re: Find if keys are in two dimensional associative array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen kjaeraas | On Sun, 17 Jan 2010 18:02:00 +0100, Simen kjaeraas wrote:
> 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!" );
> }
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.
|
January 17, 2010 Re: Find if keys are in two dimensional associative array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michal Minich | 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 |
Copyright © 1999-2021 by the D Language Foundation