www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Array.sort understanding need

reply jicman <jicman_member pathlink.com> writes:
Greetings!

Imagine this code,

|import std.string;
|import std.stdio;
|class DAEError
|{
|  char[] name  = "";
|  int Count = 0;
|}
|
|void main()
|{
|  DAEError Err[];
|  Err.length = Err.length + 1;
|  Err[Err.length - 1] = new DAEError();
|  Err[Err.length - 1].name = "A";
|  Err[Err.length - 1].Count++;
|  Err.length = Err.length + 1;
|  Err[Err.length - 1] = new DAEError();
|  Err[Err.length - 1].name = "B";
|  Err[Err.length - 1].Count++;
|  Err.length = Err.length + 1;
|  Err[Err.length - 1] = new DAEError();
|  Err[Err.length - 1].name = "C";
|  Err[Err.length - 1].Count++;
|  Err.length = Err.length + 1;
|  Err[Err.length - 1] = new DAEError();
|  Err[Err.length - 1].name = "D";
|  Err[Err.length - 1].Count++;
|  Err.length = Err.length + 1;
|  Err[Err.length - 1] = new DAEError();
|  Err[Err.length - 1].name = "a";
|  Err[Err.length - 1].Count++;
|  Err.length = Err.length + 1;
|  Err[Err.length - 1] = new DAEError();
|  Err[Err.length - 1].name = "b";
|  Err[Err.length - 1].Count++;
|  Err.length = Err.length + 1;
|  Err[Err.length - 1] = new DAEError();
|  Err[Err.length - 1].name = "c";
|  Err[Err.length - 1].Count++;
|  Err = Err.sort;
|  foreach (int error, DAEError e; Err)
|    writefln(Err[error].name, " ", toString(Err[error].Count));
|}

If I compile this code and run it, I get,

jic 11:01:19-> ./sort
c 1
b 1
a 1
D 1
C 1
B 1
A 1

This is not what I expected at all.  But, I must say that the sort function does
work great with char[][] arrays.  But, on this one, I would expect to have .name
and then, .Count be the sorting keys, in that order.  Am I crazy or just don't
understand sort?

thanks,

josť
Aug 05 2005
parent reply Vathix <chris dprogramming.com> writes:
On Fri, 05 Aug 2005 11:11:13 -0400, jicman <jicman_member pathlink.com>  
wrote:

 Greetings!

 Imagine this code,

 |import std.string;
 |import std.stdio;
 |class DAEError
 |{
 |  char[] name  = "";
 |  int Count = 0;
 |}

Add opCmp() and opEquals() to the class and tell it how to sort.
Aug 05 2005
parent reply jicman <jicman_member pathlink.com> writes:
Vathix says...
On Fri, 05 Aug 2005 11:11:13 -0400, jicman <jicman_member pathlink.com>  
wrote:

 Greetings!

 Imagine this code,

 |import std.string;
 |import std.stdio;
 |class DAEError
 |{
 |  char[] name  = "";
 |  int Count = 0;
 |}

Add opCmp() and opEquals() to the class and tell it how to sort.

Thanks. However, I have been looking at this page, http://www.digitalmars.com/d/operatoroverloading.html and pardon my D ignorance and/or c, but I have never used OpCmp() nor opEquals(). I have gone into the web and search for "sorting array opCmp() opEquals()" and found a few pages, but none really shows any examples. Will anyone be willing to point me to an example that uses what Vathix has suggested? Thanks again. josť
Aug 05 2005
parent reply Vathix <chris dprogramming.com> writes:
import std.stdio, std.string;

class Foo
{
    char[] str;
    int num;

    this(char[] str, int num)
    {
       this.str = str;
       this.num = num;
    }

    override char[] toString()
    {
       return format("'%s' %d", str, num);
    }

    override int opCmp(Object obj) // Override from Object.
    {
       Foo f;
       f = cast(Foo)obj;
       if(f)
          return opCmp(f); // Use opCmp(Foo).
       assert(0); // Wrong type.
    }

    int opCmp(Foo f)
    {
       int result;
       result = std.string.cmp(str, f.str);
       if(!result) // If match, compare num`s.
          result = num - f.num;
       return result;
    }

    override int opEquals(Object obj) // Override from Object.
    {
       Foo f;
       f = cast(Foo)obj;
       if(f)
          return opEquals(f); // Use opEquals(Foo).
       assert(0); // Wrong type.
    }

    int opEquals(Foo f)
    {
       int result;
       result = str != f.str;
       if(!result) // If match, compare num`s.
          result = num - f.num;
       return result;
    }
}

int main()
{
    Foo[8] fs;

    fs[0] = new Foo("foo", 3);
    fs[1] = new Foo("foo", 1);
    fs[2] = new Foo("candy", 4);
    fs[3] = new Foo("foo", 5);
    fs[4] = new Foo("gum", 5);
    fs[5] = new Foo("zoo", 9);
    fs[6] = new Foo("bar", 9);
    fs[7] = new Foo("fun", 88);

    fs.sort;

    foreach(Foo f; fs)
    {
       writefln("%s", f.toString());
    }

    return 0;
}
Aug 05 2005
parent jicman <jicman_member pathlink.com> writes:
Vathix says...
import std.stdio, std.string;

class Foo
{
    char[] str;
    int num;

    this(char[] str, int num)
    {
       this.str = str;
       this.num = num;
    }

    override char[] toString()
    {
       return format("'%s' %d", str, num);
    }

    override int opCmp(Object obj) // Override from Object.
    {
       Foo f;
       f = cast(Foo)obj;
       if(f)
          return opCmp(f); // Use opCmp(Foo).
       assert(0); // Wrong type.
    }

    int opCmp(Foo f)
    {
       int result;
       result = std.string.cmp(str, f.str);
       if(!result) // If match, compare num`s.
          result = num - f.num;
       return result;
    }

    override int opEquals(Object obj) // Override from Object.
    {
       Foo f;
       f = cast(Foo)obj;
       if(f)
          return opEquals(f); // Use opEquals(Foo).
       assert(0); // Wrong type.
    }

    int opEquals(Foo f)
    {
       int result;
       result = str != f.str;
       if(!result) // If match, compare num`s.
          result = num - f.num;
       return result;
    }
}

int main()
{
    Foo[8] fs;

    fs[0] = new Foo("foo", 3);
    fs[1] = new Foo("foo", 1);
    fs[2] = new Foo("candy", 4);
    fs[3] = new Foo("foo", 5);
    fs[4] = new Foo("gum", 5);
    fs[5] = new Foo("zoo", 9);
    fs[6] = new Foo("bar", 9);
    fs[7] = new Foo("fun", 88);

    fs.sort;

    foreach(Foo f; fs)
    {
       writefln("%s", f.toString());
    }

    return 0;
}

Any questions? :-) Thank you. I appreciate it very much. Never done this, so this example is perfect. josť
Aug 05 2005