|
Archives
D Programming
digitalmars.D
digitalmars.D.bugs
digitalmars.D.dtl
digitalmars.D.ide
digitalmars.D.dwt
digitalmars.D.announce
digitalmars.D.learn
digitalmars.D.debugger
D.gnu
D
C/C++ Programming
c++
c++.announce
c++.atl
c++.beta
c++.chat
c++.command-line
c++.dos
c++.dos.16-bits
c++.dos.32-bits
c++.idde
c++.mfc
c++.rtl
c++.stl
c++.stl.hp
c++.stl.port
c++.stl.sgi
c++.stlsoft
c++.windows
c++.windows.16-bits
c++.windows.32-bits
c++.wxwindows
digitalmars.empire
digitalmars.DMDScript
electronics
|
digitalmars.D.learn - 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;
}
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
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...
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
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...
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
Michal Minich wrote:
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.
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.
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
Ali Çehreli:
I don't know the answer, but the spec says so at
I have already given the answer, the hash collisions are resolved with an
ordered search tree.
Bye,
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...
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
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.
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
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;
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
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=3709
Thank you, but it is some other issue. I posted enhacement request already
http://d.puremagic.com/issues/show_bug.cgi?id=3718
|
|