.NET Forum / Languages / C# / March 2008
Using IComparer to Sort a String Array
|
|
Thread rating:  |
Jeta - 26 Mar 2008 13:21 GMT Hello All,
I stumped and I need some help. I have an unsorted string array that looks something like: AA XXX Z
and I would like to sort it like: Z AA XXX
or like: XXX AA Z
My research has lead me to using the IComparer interface. What I am having difficulties with is developing a class that will take an unsorted string array (as noted above) and return a sorted string array (as noted above) using the IComparer interface.
Thanks in Advance!
Marc Gravell - 26 Mar 2008 13:46 GMT I'm assuming that "XXX" is some secial value that you want to highlight?
Anyways... something like below.
Marc
using System; using System.Collections.Generic; using System.Collections;
public class XxxComparer : IComparer<string>, IComparer { public static readonly IComparer<string> Default = new XxxComparer(); const string KNOWN_VAL = "XXX"; public int Compare(string lhs, string rhs) { if (lhs == KNOWN_VAL) { return rhs == KNOWN_VAL ? 0 : -1; } else if (rhs == KNOWN_VAL) { return 1; } return string.Compare(lhs, rhs); } int IComparer.Compare(object lhs, object rhs) { return Compare(lhs as string, rhs as string); } } static class Program { static void Main() { string[] vals = { "AA", "XXX", "Z" }; Array.Sort<string>(vals, XxxComparer.Default); foreach (string val in vals) { Console.WriteLine(val); } } }
Jeta - 26 Mar 2008 15:19 GMT Hi Marc,
Thank you for your response!
In the context of your XxxComparer class, "XXX" has no special meaning. In Main() is where it becomes important (not the XXX, but the highest letter(s)) All I need is a "comparer" class to return a sorted array. Once returned, I would like to procure the highest value from the first or last element of the array. Note, the unsorted string array that I provided was just a sample. The unsorted sample array could have looked like the following examples:
example 1 A B C Z AA AZ AC AB
example 2 ZZX ZZY ZZZ
Also, in your code, you have "using System.Collections.Generic;", I think this was introduced in .Net 2.0, the company that I work for is making me compile my "stuff" down to .Net 1.1 I mention this because I am not sure if your technique will work for .Net 1.1
Thanks Again!
> I'm assuming that "XXX" is some secial value that you want to > highlight? [quoted text clipped - 40 lines] > } > } Marc Gravell - 26 Mar 2008 16:18 GMT Re the XXX - I was (and still am) unclear about what the sort order should be - is this "by length"? because otherwise as far as I am concerned, AA, XXX, Z is already sorted. The IComparer approach should work in 1.1, but I don't have any 1.1 tools available to verify; but the following *might* compile in 1.1 ;-p
using System; using System.Collections;
public class XxxComparer : IComparer { public static readonly IComparer Default = new XxxComparer(); const string KNOWN_VAL = "XXX"; public int Compare(string lhs, string rhs) { if (lhs != null && rhs != null) { int result = lhs.Length.CompareTo(rhs.Length); if (result != 0) return result; } return lhs.CompareTo(rhs); } int IComparer.Compare(object lhs, object rhs) { return Compare(lhs as string, rhs as string); } } static class Program { static void Main() { string[] vals = { "AA", "XXX", "Z" }; Array.Sort(vals, XxxComparer.Default); foreach (string val in vals) { Console.WriteLine(val); } } }
Jeta - 26 Mar 2008 17:06 GMT >>...as far as I am concerned, AA, XXX, Z is already sorted. If the sort is occurring on the first character, you are 100% correct. Using the AA, XXX, Z example, I see XXX being greater than Z.
FYI, the letters that I am describing are actually revision levels coming from a CAD drawing. What I am trying to do is get the last revision level from an array - in this case the last revision level would be XXX
Thanks
> Re the XXX - I was (and still am) unclear about what the sort order > should be - is this "by length"? because otherwise as far as I am [quoted text clipped - 34 lines] > } > } Marc Gravell - 26 Mar 2008 21:10 GMT > If the sort is occurring on the first character, you are 100% correct. Using > the AA, XXX, Z example, I see XXX being greater than Z. Maybe I'm being really slow today - but would you care to explain those rules? Why would the last revision be XXX? Is the problem is that you want 123 to follow 29? In which case, the code I posted last time might do the job... it compares by length first, and (for equal length) compares as normal...
Marc
Jeta - 27 Mar 2008 16:21 GMT Hi Marc,
>> Maybe I'm being really slow today No! I was probably not explaining myself clear enough.
>> but would you care to explain those rules? XXX was just an example. Actually, the highest revision level is ZZZ for mechanical engineering CAD drawings and 999 for architectural engineering CAD drawings. Now you may ask :-) why would the last revision level be ZZZ or 999? My response is it's a company standard.
Our CAD drawings have a placeholder for a maximum of three revision levels. When a new mechanical engineering CAD drawing is created it's revision level is "A". When a change is made, to this type of CAD drawing, the revision level is incremented to the next letter. This process is repeated for each engineering change.
Since I stated there's a placeholder for a maximum of three revision levels, revision "D" would replace the revision "A", revision "E" would replace revision "B" and revision "F" would replace revision "C", etc., etc., etc.
When the last revision is "Z", the next revision would be "AA" followed by "AB", "AC", "AD", ...,"AZ", "BA", "BB", ...,"BZ", ...,"ZA", ..., "ZZ", "AAA", ...,"AAZ", etc., etc., etc. So, theoretically a mechanical engineering CAD drawing could have 17,576 revisions. Will there ever be that many revision levels? NO WAY!
I hope the above wasn't to much babble!
>> Is the problem is that you want 123 to follow 29? Yes, Yes, Yes :-) I haven't tested your code with numbers, but I have tested it with letters. Here's an example. Your code will sort the following string array: Z AA AB
Like this: AA AB Z
I needed it to be sorted like: Z AA AB
After studying your code and other responses, here's what I came up with: public class sortRevision : IComparer { int IComparer.Compare(Object x, Object y) { int val = ((new CaseInsensitiveComparer()).Compare(x, y)); string localx = (string)x; string localy = (string)y;
if (val < 0) { if (localx.Length > localy.Length) val = 1; } if (val > 0) { if (localx.Length < localy.Length) val = -1; } return val; } }
I am calling the above as follows: Array.Sort(allRevLevels, (IComparer)new sortRevision());
Any suggestions are welcome and greatly appreciated!
Thanks!
>> If the sort is occurring on the first character, you are 100% correct. >> Using [quoted text clipped - 7 lines] > > Marc Ben Voigt [C++ MVP] - 26 Mar 2008 14:30 GMT > Hello All, > [quoted text clipped - 18 lines] > unsorted string array (as noted above) and return a sorted string > array (as noted above) using the IComparer interface. You probably really want the Comparison(T) delegate, but the List.Sort method will work with either.
Something like:
int ConvertColumnName(string s) { int total = 0; foreach (char c in s) total = total * 26 + (c - 'A' + 1); return total; }
The for ascending or descending sort:
List<string> l; l.Sort(delegate (string first, string second) { return ConvertColumnName(first) - ConvertColumnName(second); }); l.Sort(delegate (string first, string second) { return ConvertColumnName(second) - ConvertColumnName(first); });
Ignacio Machin ( .NET/ C# MVP ) - 26 Mar 2008 16:10 GMT > Hello All, > [quoted text clipped - 20 lines] > > Thanks in Advance! Hi,
Yes, you need to create a class that implements the IComparer. There are other ways though, depending of what kind of collection you have and what version of the framework you are using If you are using 2.0+ and a generic collectin you can do something like:
myList.Sort(delegate(string T1, string T2) { return T1.CompareTo(T2); });
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|