Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / March 2008

Tip: Looking for answers? Try searching our database.

Using IComparer to Sort a String Array

Thread view: 
Enable EMail Alerts  Start New Thread
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 Magazines

Get 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 ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.