tags:

views:

230

answers:

3

Is it possible to sort a list using two values in an object with iComparer?

I've got a custom comparer class that sorts based on value1. But what's the best way to get a sort on value1 and value2?

Would sorting the list by value2 then value1 work?

+4  A: 

Your IComparer class should handle it. For example:

public class ThingComparer : IComparer
{
    public int Compare(object x, object y)
    {
        // null- and type-checking omitted for clarity

        // sort by A, B, and then C

        if (x.A != y.A) return x.A.CompareTo(y.A);
        if (x.B != y.B) return x.B.CompareTo(y.B);
        return x.C.CompareTo(y.C);
    }
}
mquander
Great! Thanks for quick response
steve
I've always done this by using weights and comparing all three items. Never thought to do it like this, I guess it was too simple ;)
AlexCuse
A: 

If you implement your own comparer you can perform any sort you want:

List<Customer> customers = GetCustomers();
customers.Sort(delegate(Customer x, Customer y)
{
    if (x.Name != y.Name)
    {
        return x.Name.CompareTo(y.Name);
    }

    return x.Location.CompareTo(y.Location);
});

Now the above code is not an IComparer class, but the comparison approach is the same.

Fredrik Mörk
A: 
public class ScratchComparer : IComparer<Scratch>
{
    public int Compare(Scratch x, Scratch y)
    {
     return x.Foo.CompareTo(y.Foo).CompareTo(0.CompareTo(x.Bar.CompareTo(y.Bar)));
    }
}

[TestFixture]
public class Scratch
{
    public virtual int Foo { get; set; }
    public virtual int Bar { get; set; }

    [Test]
    public void Should_sort()
    {
     var scratches = new[]
     {
      new Scratch {Foo = 1, Bar = 1},
      new Scratch {Foo = 2, Bar = 1},
      new Scratch {Foo = 1, Bar = 1},
      new Scratch {Foo = 1, Bar = 2}
     };

     // IComparer
     Array.Sort(scratches, new ScratchComparer());

     scratches[0].Foo.ShouldEqual(1);
     scratches[0].Bar.ShouldEqual(1);

     scratches[1].Foo.ShouldEqual(1);
     scratches[1].Bar.ShouldEqual(1);

     scratches[2].Foo.ShouldEqual(1);
     scratches[2].Bar.ShouldEqual(2);

     scratches[3].Foo.ShouldEqual(2);
     scratches[3].Bar.ShouldEqual(1);

     // better
     Scratch[] ordered = scratches.OrderBy(x => x.Foo).ThenBy(x => x.Bar).ToArray();

     ordered[0].Foo.ShouldEqual(1);
     ordered[0].Bar.ShouldEqual(1);

     ordered[1].Foo.ShouldEqual(1);
     ordered[1].Bar.ShouldEqual(1);

     ordered[2].Foo.ShouldEqual(1);
     ordered[2].Bar.ShouldEqual(2);

     ordered[3].Foo.ShouldEqual(2);
     ordered[3].Bar.ShouldEqual(1);
    }
}
Matt Hinze
An impressive feat of engineering.
mquander