how hash_t toHash() works?
gedaiu
szabobogdan at yahoo.com
Mon Apr 29 08:19:25 PDT 2013
On Sunday, 28 April 2013 at 13:18:04 UTC, Ivan Kazmenko wrote:
> Hi,
>
>> I have a class which I want to use as key in an assoc array
>> like
>> this:
>>
>> string["KeyString"] myArray;
>>
>> What i want is to preserve the order in the array. I want
>> always
>> to have "1" before "2" if the string is a numeric value.
>>
>> Can anyone help me to understand how const hash_t toHash()
>> should
>> work?
>
> Associative arrays in D are implemented as hash tables.
> Hashing sacrifices ordering capabilities for greater speed.
> Creating a hash table will most certainly take your toHash
> value modulo some integer you can not control (small for small
> tables, large for larger ones). It would be crippling, if at
> all possible, to have foreach on an associative array always
> produce a sorted result.
>
> I'd suggest using std.container.RedBlackTree instead. It
> doesn't provide syntactic sugar (like "container[key] = value")
> but preserves the ordering.
>
> Also note that sorting items as strings should be separated
> from sorting as integers. For example, a value convertible to
> integer should be always less (or always greater) than a
> non-convertible value. Otherwise, it would quickly lead to
> inconsistent comparisons, as in "22" <s "22a" <s "4" <n "22".
> Here, "<s" compares values as strings and "<n" as integers.
>
> Below is an example of using RedBlackTree close to what you
> might need:
>
> -----
> import std.container;
> import std.conv;
> import std.stdio;
>
> bool doConv(out long val, string s) {
> try {
> val = to!long(s);
> return true;
> }
> catch(ConvException) {
> return false;
> }
> }
>
> struct KeyString {
> string str;
>
> KeyString opAssign(string val) {
> str = val;
> return this;
> }
>
> const int opCmp(ref const KeyString s) {
> long v1, v2;
> auto b1 = doConv(v1, str);
> auto b2 = doConv(v2, s.str);
> if (b1 != b2) return b2 - b1;
> if (b1 && b2) return (v1 > v2) - (v1 < v2);
> return std.string.cmp(str, s.str);
> }
> }
>
> struct MyRecord {
> KeyString key;
> int val;
>
> this(string nkey, int nval) {
> key = nkey;
> val = nval;
> }
> }
>
> void main () {
> auto cont = redBlackTree !("a.key < b.key", true, MyRecord) ();
> cont.insert(MyRecord("1", 1));
> cont.insert(MyRecord("111", 2));
> cont.insert(MyRecord("25", 3));
> cont.insert(MyRecord("53", 4));
> cont.insert(MyRecord("a", 5));
> cont.insert(MyRecord(" ", 6));
> cont.insert(MyRecord("1234567890123456789", 7));
> cont.insert(MyRecord("12345678901234567890", 8));
> foreach (ref const cur; cont) {
> writefln("cont[\"%s\"] = %s", cur.key.str, cur.val);
> }
> }
> -----
>
> The example prints:
>
> -----
> cont["1"] = 1
> cont["25"] = 3
> cont["53"] = 4
> cont["111"] = 2
> cont["1234567890123456789"] = 7
> cont[" "] = 6
> cont["12345678901234567890"] = 8
> cont["a"] = 5
> -----
>
> The last three entries are strings not convertible to a long,
> so they are ordered lexicographically.
>
> Ivan Kazmenko.
Thanks!
it looks great!
one more questionWhat is the type of cont?
auto cont = redBlackTree !("a.key < b.key", true, MyRecord) ();
I want to use this as a property in a class and i can't use there
auto keyword... I tried different types but it did not work.
Bogdan
More information about the Digitalmars-d-learn
mailing list