Domanda

I'm sure this is simple but it has me stumped. I want, simplified, to sort my alphabet but putting Ds between As and Bs. I think I want a custom IComparer to do this.

How would I finish this IComparer implementation to pass my Assertion? The IComparer documentation says to return less than 0 if x is < y, but does it matter how much less than zero? Scratching my head.

private static void Main(string[] args)
{
    var letters = new List<string> { "A2", "E", "B1", "A1", "D", "C", "B2" };
    var sorted = new List<string> { "A1", "A2", "D", "B1", "B2", "C", "E" };

    letters.Sort(new MyComparer());

    Assert.IsTrue(letters.SequenceEqual(sorted));
}

/// <summary>
/// Sorts D between A and B
/// </summary>
private class MyComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        if (string.Equals(x, "D"))
        {
            // return what?
        }
        return string.CompareOrdinal(x, y);
    }
}
È stato utile?

Soluzione

but does it matter how much less than zero

Nope, not at all.

Basically each comparison has to give a single result from three options:

  • First value is less than second value
  • Values are equal
  • First value is more than second value

So to make "D" come between "A" and "B" you'd use something like:

public int Compare(string x, string y)
{
    if (x == y)
    {
        return 0;
    }
    if (x == "D")
    {
        // Unless y is *actually* "B", we can just
        // pretend that x is "B". (So it will be after any "A", but before
        // any other "Bxyz".)
        if (y == "B")
        {
            return -1;
        }
        return "B".CompareTo(y);
    }
    // Ditto, basically. Alternatively you could call Compare(y, x)
    // and invert the result, but *don't* just negate it, as it does the
    // wrong thing with int.MinValue...
    if (x == "D")
    {
        if (x == "B")
        {
            return 1;
        }
        return x.CompareTo("B");
    }
    return x.CompareTo(y);
}

Altri suggerimenti

It would be easier to modify sort order by using Linq:

letters.OrderBy(x=>EvaluationFunction(x));

The actual EvaluationFunction depends on your actual business requirements for sorting.

The order you're looking at doesn't make much sense to me, I can't guess the rule (why is the "D" there?) but if the order were A1, A2, B1, B2, C, D, E

your EvaluationFunction can be:

string EvaluationFunction(string s){
    return  string.Format("{0,-3}", s); // pads s on the left with spaces, up to 3
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top