Jump to page: 1 2
Thread overview
Find if keys are in two dimensional associative array
Jan 17, 2010
Michal Minich
Jan 17, 2010
Mike Wey
Jan 17, 2010
Michal Minich
Jan 17, 2010
bearophile
Jan 17, 2010
Michal Minich
Jan 17, 2010
bearophile
Jan 17, 2010
Michal Minich
Jan 17, 2010
Ali Çehreli
Jan 18, 2010
bearophile
Jan 17, 2010
Simen kjaeraas
Jan 17, 2010
Michal Minich
Jan 17, 2010
Simen kjaeraas
Jan 17, 2010
BCS
Jan 19, 2010
Jesse Phillips
Jan 19, 2010
Michal Minich
January 17, 2010
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
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
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
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
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
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
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
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
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
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
« First   ‹ Prev
1 2