Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom string Comparison in C#

Tags:

string

c#

sorting

I want to implement a custom string IComparer in C# and apply it to a ComboBox.

Actual Results

If I set the ComboBox's Sorted property to true, the output is :

A
AA
AAA
B
BB
BBB

Wanted Results

The wanted behavior of the sorting algorithm is the following (financial developers will understand why :) ) :

AAA
AA
A
BBB
BB
B

Question

Is it possible to do it ? Are sorting algorithms needed here ?

PS : I don't need a complete answer with code, i just need an idea of how it might be done ..

EDIT

This is about credit ratings. I've omitted something in my question. The ratings have to be sorted in this order :

XXX
XX+
XX
XX-
X+
X
X-

with X in ('A','B','C') and 'A' > 'B' > 'C'

like image 929
Fares Avatar asked Jul 02 '13 17:07

Fares


People also ask

How do you compare strings in C?

The strcmp() function, is used to compare the strings (str1,str2). The strings str1 and str2 will be compared using this function. If the function returns a value 0, it signifies that the strings are equal otherwise, strings are not equal.

Can I use == to compare strings in C?

In C, string values (including string literals) are represented as arrays of char followed by a 0 terminator, and you cannot use the == operator to compare array contents; the language simply doesn't define the operation.

How do you compare 2 strings?

Using String. equals() :In Java, string equals() method compares the two given strings based on the data/content of the string. If all the contents of both the strings are same then it returns true. If any character does not match, then it returns false.

Can we use == for string comparison?

You should not use == (equality operator) to compare these strings because they compare the reference of the string, i.e. whether they are the same object or not. On the other hand, equals() method compares whether the value of the strings is equal, and not the object itself.


2 Answers

Here's a mostly implemented version:

public class MyComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        //todo null checks on input

        var pairs = x.Zip(y, (a, b) => new { x = a, y = b });

        foreach (var pair in pairs)
        {
            int value = pair.x.CompareTo(pair.y);
            if (value != 0)
                return value;
        }


        //if we got here then either they are the same,
        //or one starts with the other
        return y.Length.CompareTo(x.Length); //note x and y are reversed here
    }
}

So this uses Zip to get the pairs of chars from each corresponding string until one ends, returning the appropriate value if they aren't equal. If it makes it past that then one string start with the other. For a traditional string comparison we'd just compare the lengths in the same order as the input parameters. Since we're essentially reversing the order based on length, note that the x and y are swapped on the last line. That reverses the comparison logic.

like image 95
Servy Avatar answered Oct 13 '22 10:10

Servy


Assuming this is for credit ratings, normally this is done by having a "sort order" column on the CreditRating class that you could use to sort the list before assigning it as the data source of the drop-down.

But, a quick workaround (based on the limited possible values) would be to sort by the first letter ascending, then by the length of the string descending:

if(left[0] != right[0])
    return left[0].CompareTo(right[0]);
else
    return right.Length - left.Length;

Another workaround if you want more control over the order is to create a list of possible values in the "right" order and then use that to sort the list:

public class MyComparer : IComparer<string>
{
    private static readonly string[] Ratings = new [] {
        "CC","C","CCC-","CCC","CCC+",
        "B-","B","B+","BB-","BB","BB+","BBB-","BBB","BBB+",
        "A-","A","A+","AA-","AA","AA+","AAA"};
    // reverse the order so that any strings not found will be put at the end.

    public int Compare(string left, string right)
    {
       return Array.IndexOf(Ratings, right).CompareTo(Array.IndexOf(Ratings, left));
    }
}
like image 27
D Stanley Avatar answered Oct 13 '22 09:10

D Stanley