digitalmars.D - Custom opCmp for struct array sort
- New (44/44) Nov 28 2008 Hello,
- bearophile (35/36) Nov 28 2008 This may work (D1), I have cleaned up your code some:
- New (6/54) Nov 28 2008 Hello,
- bearophile (6/8) Nov 28 2008 I don't agree, it's called:
- New (4/17) Nov 28 2008 I see, sorry about that, I missed the D1 bit in your message and tested ...
- bearophile (6/9) Nov 28 2008 No, surely D2 isn't "production ready", it's alpha stage. D1 is barely l...
- BCS (3/8) Nov 28 2008 I'd say it more of a 1.0 release version. Heck windows was a piece of ju...
- Steven Schveighoffer (21/70) Dec 01 2008 The problem is the opCmp function signature.
Hello, I am new with D and am stuck with something I hope somebody can help me with it. I am trying sort an array of paths which can take the two following forms: /usr ---> normal path /bin=/other/bin ---> a symlink When I sort these paths, in the case of symlinks I want to ignore the right hand side and I just use the path before the "=" sign. The array docs for DMD 2.0, say that can create a structure and create a opCmp function to cutomise the way sort works. I have tried this but calling .sort does not seem to pick-up my custom opCmp. Any help would be very appreciated. I am including the code below Thanks a lot -------------------------------------------------------------------- struct Path { invariant(char) [] thePath; int opCmp(Path p) { int pos; invariant(char) [] a; invariant(char) [] b; if( (pos=find(this.thePath, RegExp("="))) > -1 ) { a = this.thePath[0 .. pos]; } else { a = this.thePath; } if( (pos=find(p.thePath, RegExp("="))) > -1 ) { b = p.thePath[0 .. pos]; } else { b = p.thePath; } int cosa = std.string.cmp(a, b); writefln( a, " comp ", b, "=", cosa); return std.string.cmp(a, b); } } int main(char[][] args) { char[][][Path] contents; Path one; one.thePath = "/002=/other_dir"; contents[one] = cast(char[][])["aa","bb","cc","dd"]; Path two; two.thePath = "/001"; contents[two] = cast(char[][])["aa","bb","cc","dd"]; foreach(item; contents.keys.sort) { writefln( item.thePath ); } return 0; }
Nov 28 2008
New:When I sort these paths, in the case of symlinks I want to ignore the right hand side and I just use the path before the "=" sign.This may work (D1), I have cleaned up your code some: import std.string: find, cmp; import std.stdio: writefln; struct Path { string thePath; int opCmp(Path other) { int pos; string a, b; pos = find(this.thePath, "="); if (pos > -1) a = this.thePath[0 .. pos]; else a = this.thePath; pos = find(other.thePath, "="); if (pos > -1) b = other.thePath[0 .. pos]; else b = other.thePath; return cmp(a, b); } } void main() { string[][Path] contents = [ Path("/002=/other_dir"): ["aa","bb","cc","dd"], Path("/001"): ["aa","bb","cc","dd"], Path("/002=/hello") : ["aa","bb","cc","dd"] ]; foreach (item; contents.keys.sort) writefln(item.thePath); } Note that you may not need it, because the part before = is on the left, so just sorting the strings may give you the order you need, without using any opCmp. For other similar questions the D.learn newsgroup is fitter. Bye, bearophile
Nov 28 2008
Hello, Thanks for cleaning up the code, I was getting a bit annoyed with the all the invariants, but I did not know how to get rid of them. I tried your version but still the opCmp is not called :( I will try on D.learn thanks very much bearophile Wrote:New:When I sort these paths, in the case of symlinks I want to ignore the right hand side and I just use the path before the "=" sign.This may work (D1), I have cleaned up your code some: import std.string: find, cmp; import std.stdio: writefln; struct Path { string thePath; int opCmp(Path other) { int pos; string a, b; pos = find(this.thePath, "="); if (pos > -1) a = this.thePath[0 .. pos]; else a = this.thePath; pos = find(other.thePath, "="); if (pos > -1) b = other.thePath[0 .. pos]; else b = other.thePath; return cmp(a, b); } } void main() { string[][Path] contents = [ Path("/002=/other_dir"): ["aa","bb","cc","dd"], Path("/001"): ["aa","bb","cc","dd"], Path("/002=/hello") : ["aa","bb","cc","dd"] ]; foreach (item; contents.keys.sort) writefln(item.thePath); } Note that you may not need it, because the part before = is on the left, so just sorting the strings may give you the order you need, without using any opCmp. For other similar questions the D.learn newsgroup is fitter. Bye, bearophile
Nov 28 2008
New Wrote:Thanks for cleaning up the code, I was getting a bit annoyed with the all the invariants, but I did not know how to get rid of them.Note that my code is D1.I tried your version but still the opCmp is not called :(I don't agree, it's called: http://codepad.org/FLVu8gqQ Bye, bearophile
Nov 28 2008
I see, sorry about that, I missed the D1 bit in your message and tested on D2, what would I need to do to make it run on D2? Is D2 production ready?, is it better to use D1? thanks bearophile Wrote:New Wrote:Thanks for cleaning up the code, I was getting a bit annoyed with the all the invariants, but I did not know how to get rid of them.Note that my code is D1.I tried your version but still the opCmp is not called :(I don't agree, it's called: http://codepad.org/FLVu8gqQ Bye, bearophile
Nov 28 2008
New Wrote:what would I need to do to make it run on D2?I don't know, sorry :-)Is D2 production ready?No, surely D2 isn't "production ready", it's alpha stage. D1 is barely like that, despite being a stable beta.is it better to use D1?D2 is now mostly for testing, I presume. But you are free to use it, it works. Bye, bearophile
Nov 28 2008
Reply to bearophile,New Wrote:I'd say it more of a 1.0 release version. Heck windows was a piece of junk for v1 and v2.</joke>is it better to use D1?D2 is now mostly for testing, I presume. But you are free to use it, it works.
Nov 28 2008
"New" wroteHello, I am new with D and am stuck with something I hope somebody can help me with it. I am trying sort an array of paths which can take the two following forms: /usr ---> normal path /bin=/other/bin ---> a symlink When I sort these paths, in the case of symlinks I want to ignore the right hand side and I just use the path before the "=" sign. The array docs for DMD 2.0, say that can create a structure and create a opCmp function to cutomise the way sort works. I have tried this but calling .sort does not seem to pick-up my custom opCmp. Any help would be very appreciated. I am including the code below Thanks a lot -------------------------------------------------------------------- struct Path { invariant(char) [] thePath; int opCmp(Path p) { int pos; invariant(char) [] a; invariant(char) [] b; if( (pos=find(this.thePath, RegExp("="))) > -1 ) { a = this.thePath[0 .. pos]; } else { a = this.thePath; } if( (pos=find(p.thePath, RegExp("="))) > -1 ) { b = p.thePath[0 .. pos]; } else { b = p.thePath; } int cosa = std.string.cmp(a, b); writefln( a, " comp ", b, "=", cosa); return std.string.cmp(a, b); } } int main(char[][] args) { char[][][Path] contents; Path one; one.thePath = "/002=/other_dir"; contents[one] = cast(char[][])["aa","bb","cc","dd"]; Path two; two.thePath = "/001"; contents[two] = cast(char[][])["aa","bb","cc","dd"]; foreach(item; contents.keys.sort) { writefln( item.thePath ); } return 0; }The problem is the opCmp function signature. One of the undocumented (as far as I know) features of the compiler is that for a struct, if there is an opCmp of a certain signature, the compiler saves a function pointer to that opCmp in that struct's typeinfo as 'the' opCmp to use when comparing two of those structs. This is used in associative arrays and with sort. the appropriate signature for D2 (as of 2.019) is: struct S { int opCmp(const S *s) const; } So in order for your code to be used during sort in D 2, you need to change your signature to:int opCmp(const Path * p) const {Then it should work. If it's different in D 2.021 (and it probably should be given the advent of 'SafeD' requiring no pointers), then I don't know what it might be, but I'd guess you'd replace 'const Path *p' with 'ref const Path p'. I think these 'special' features should be documented, probably in the operators page. I'll file a bugzilla request. -Steve
Dec 01 2008