www.digitalmars.com         C & C++   DMDScript  

D - associative arrays? how to use them?

reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
I first have to say that i am sory for asking this question again!

I tried for a long time but i just can't understand how associative arrays
work?

First a simple example: (this works)

 int[char[]] assoc;
 assoc["ivan"]=1; //assoc.length == 1
 assoc["ira"]=2;  //assoc.length == 2
 assoc["ivan"]=3; //assoc.length == 2

 char[] name;
  name~= "i";
  name~= "v";
  name~= "a";
  name~= "n";

 char[] name2;
  name2~= "i";
  name2~= "v";
  name2~= "a";
  name2~= "n";

 char[] name3 = "_ivan_"[1..5];

 assoc[name]=4;      //assoc.length == 2
 assoc[name2]=5;    //assoc.length == 2
 assoc[name3]=6;    //assoc.length == 2

This example works the way i expect it to work: when i insert the same
element
again the length doesn't increase!

Example 2: (associative array with class key)

class Point
{
 int x,y;
 this(int x,int y)
 {
  this.x=x;
  this.y=y;
 }
 int opEquals(Point x)
 {
  if(this.x == x.x && this.y == x.y)return 1;
  else return 0;
 }
 uint toHash()
 {
  return this.x + this.y;
 }
 int opCmp(in Point x)
 {
  if(this.x < x.x){return -1;}
  if(this.x > x.x){return 1;}
  if(this.y < x.y){return -1;}
  if(this.y >= x.y){return 1;}
 }
}

int main(char [] [] args)
{
 int[Point] assoc2;

 Point t = new Point(6,7);

 assoc2[new Point(1,2)]=1;     //assoc2.length==1

 assoc2[new Point(1,2)]=2;     //assoc2.length==2 !!žbut the same point(1,2)
is inserted

 assoc2[new Point(6,7)]=3; //assoc2.length==3

 assoc2[t]=4;   //assoc2.length==4 !!    the Point(6,7) is allready in the
associative array! but length increases

 assoc2[t]=5;   //assoc2.length==4
}

Is this the way it should work? When i insert the element that is already
in the array it is inserted again?
Walter said that asoociative array uses toHash() and opCmp() when the values
returned by toHash() are different but this is not true! opCmp is never
called!

It looks to me that the associative array is only looking at the adress of
the inserted object, but if i wanted to keep track of instances of objects
using associative array i can always use associative array where index is a
pointer
to an object!
I want to keep track of different objects (by different i mean opEquals or
opCmp-diffrent)
and is this possible with associative arrays?

I tried using structs as a key but i get a compiler error:
Internal error: ..\ztc\cod1.c 1641

Help me please! I like the idea of associative array a lot but i would
like to know how to use them with class keys, and is it possible?
Mar 20 2004
next sibling parent reply Manfred Nowak <svv1999 hotmail.com> writes:
Ivan Senji wrote:

[...]
 Example 2: (associative array with class key)

Did you miss <c0vetu$167g$1 digitaldaemon.com> = D/24119 ? So long!
Mar 20 2004
parent reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Manfred Nowak" <svv1999 hotmail.com> wrote in message
news:c3ht3b$r55$1 digitaldaemon.com...
 Ivan Senji wrote:

 [...]
 Example 2: (associative array with class key)

Did you miss <c0vetu$167g$1 digitaldaemon.com> = D/24119 ? So long!

I didn't miss this. So is this behaviour of associative arrays a bug or what?
Mar 20 2004
parent Manfred Nowak <svv1999 hotmail.com> writes:
Ivan Senji wrote:

[...]
 So is this behaviour of associative arrays a bug or what?

Because DigitalMars did not answer my questions, I consider it as a bug and I am content with the workaround. However the status is open as far as I know. If you want to see it as a bug, then try if the workaround serve your understanding. If you do not want to see it as a bug, then may be, that someone is able to explain it to you. So long!
Mar 20 2004
prev sibling parent reply Ben Hinkle <bhinkle4 juno.com> writes:
 int opCmp(in Point x)
 {
  if(this.x < x.x){return -1;}
  if(this.x > x.x){return 1;}
  if(this.y < x.y){return -1;}
  if(this.y >= x.y){return 1;}
 }

opCmp needs to have the same signature as in object.d: int opCmp(Object obj) { Point x = cast(Point)obj; if (x is null) return super.opCmp(xo); if(this.x < x.x){return -1;} if(this.x > x.x){return 1;} if(this.y < x.y){return -1;} if(this.y > x.y){return 1;} return 0; }
Mar 20 2004
parent reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
Thanks!
I also had to change opEquals to have Object for parametar and it WORKS!

ivan

"Ben Hinkle" <bhinkle4 juno.com> wrote in message
news:2jvo50t4gqi0d2npoqnl98kvksm2ai3sb5 4ax.com...
 int opCmp(in Point x)
 {
  if(this.x < x.x){return -1;}
  if(this.x > x.x){return 1;}
  if(this.y < x.y){return -1;}
  if(this.y >= x.y){return 1;}
 }

opCmp needs to have the same signature as in object.d: int opCmp(Object obj) { Point x = cast(Point)obj; if (x is null) return super.opCmp(xo); if(this.x < x.x){return -1;} if(this.x > x.x){return 1;} if(this.y < x.y){return -1;} if(this.y > x.y){return 1;} return 0; }

Mar 20 2004
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Ben Hinkle wrote:
 opCmp needs to have the same signature as in object.d:


That explains something, but I still think Object.opCmp is silly. "The member function opCmp() is defined as part of Object as: int opCmp(Object o); so that every class object has a opCmp()." "For some objects, testing for less or greater makes no sense. For these, override opCmp() with: class A { int opCmp(Object o) { assert(0); // comparison makes no sense return 0; } }" Why should every object have an opCmp? This is one of D's warts I think. Surely if testing for less or greater than makes no sense, then this should be indicated by there being no opCmp method. All this does is turns what ought to be compile-time checks: - whether the class has a natural ordering at all - whether the LHS and RHS are mutually comparable, if they are of different classes into run-time checks. Maybe there's some hidden motive, but I can't see it.... Ivan Senji wrote:
 Thanks!
 I also had to change opEquals to have Object for parametar and it WORKS!

That makes a bit more sense, if there are occasions when you might want to compare objects of diverse classes for equality. (Maybe some Java programmers have taken advantage of the API containers' ability to arbitrarily mix classes....) But even templates have no difficulty finding a method opEquals(Qwert) in a class Qwert, if faced with an equality expression with two Qwerts. It isn't that difficult to clear associative arrays of this difficulty, is it? Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
Mar 22 2004
parent reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
I agree with you that this is a strange bahaviour of D, i realy can't
understand
why associative arrays us all 3 functions (opEquals, opCmp, toHash)?

I could live with it now that i know what needs to be written to make it
work,
but it would be even nicer if this where documented and explained somewhere!

"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message
news:c3n6ou$9en$1 digitaldaemon.com...
 Ben Hinkle wrote:
 opCmp needs to have the same signature as in object.d:


That explains something, but I still think Object.opCmp is silly. "The member function opCmp() is defined as part of Object as: int opCmp(Object o); so that every class object has a opCmp()." "For some objects, testing for less or greater makes no sense. For these, override opCmp() with: class A { int opCmp(Object o) { assert(0); // comparison makes no sense return 0; } }" Why should every object have an opCmp? This is one of D's warts I think. Surely if testing for less or greater than makes no sense, then this should be indicated by there being no opCmp method. All this does is turns what ought to be compile-time checks: - whether the class has a natural ordering at all - whether the LHS and RHS are mutually comparable, if they are of different classes into run-time checks. Maybe there's some hidden motive, but I can't see it.... Ivan Senji wrote:
 Thanks!
 I also had to change opEquals to have Object for parametar and it WORKS!

That makes a bit more sense, if there are occasions when you might want to compare objects of diverse classes for equality. (Maybe some Java programmers have taken advantage of the API containers' ability to arbitrarily mix classes....) But even templates have no difficulty finding a method opEquals(Qwert) in a class Qwert, if faced with an equality expression with two Qwerts. It isn't that difficult to clear associative arrays of this difficulty, is it? Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.

Mar 22 2004
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Ivan Senji wrote:
 I agree with you that this is a strange bahaviour of D, i realy can't 
 understand why associative arrays us all 3 functions (opEquals, 
 opCmp, toHash)?

- toHash - to decide which hash slot to look in - opCmp - to do a binary search within the hash slot, I guess - opEquals - to finally check that the object it's found that's comparatively equivalent is indeed equal But the opCmp stage obviously isn't going to work if the class has no ordering. Here's another difficulty - with the wart, it's tricky to detect the need to skip the opCmp stage. If the presence of an opCmp meant what it should mean, then it would be straightforward to implement an AA so that opCmp'll be used iff it exists.
 I could live with it now that i know what needs to be written to make 
 it work, but it would be even nicer if this where documented and 
 explained somewhere!

I agree. Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
Mar 23 2004