Using IComparer to Sort a String Array  
Author Message
BillSkeggs





PostPosted: Wed Mar 26 07:46:10 CDT 2008 Top

Visual C#.Net >> Using IComparer to Sort a String Array 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!

DotNet321  
 
 
Marc





PostPosted: Wed Mar 26 07:46:10 CDT 2008 Top

Visual C#.Net >> Using IComparer to Sort a String Array 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);
}
}
}
 
 
Ben





PostPosted: Wed Mar 26 08:31:37 CDT 2008 Top

Visual C#.Net >> Using IComparer to Sort a String Array Jeta wrote:
> 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.

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); });


 
 
Jeta





PostPosted: Wed Mar 26 09:19:21 CDT 2008 Top

Visual C#.Net >> Using IComparer to Sort a String Array 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!

"Marc Gravell" <EMail@HideDomain.com> wrote in message
news:EMail@HideDomain.com...
> 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);
> }
> }
> }


 
 
Ignacio





PostPosted: Wed Mar 26 10:10:56 CDT 2008 Top

Visual C#.Net >> Using IComparer to Sort a String Array On Mar 26, 8:21=A0am, "Jeta" <EMail@HideDomain.com> wrote:
> 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!

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);
});
 
 
Marc





PostPosted: Wed Mar 26 10:18:12 CDT 2008 Top

Visual C#.Net >> Using IComparer to Sort a String Array 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





PostPosted: Wed Mar 26 11:06:16 CDT 2008 Top

Visual C#.Net >> Using IComparer to Sort a String Array >>...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

"Marc Gravell" <EMail@HideDomain.com> wrote in message
news:EMail@HideDomain.com...
> 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);
> }
> }
> }


 
 
Marc





PostPosted: Wed Mar 26 15:10:43 CDT 2008 Top

Visual C#.Net >> Using IComparer to Sort a String Array > 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





PostPosted: Thu Mar 27 10:21:20 CDT 2008 Top

Visual C#.Net >> Using IComparer to Sort a String Array 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!

"Marc Gravell" <EMail@HideDomain.com> wrote in message
news:EMail@HideDomain.com...
>> 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