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