14

I have a class with 2 strings and 1 double (amount).

class Donator

  • string name
  • string comment
  • double amount

Now I have a Array of Donators filled.
How I can sort by Amount?

Jon Seigel
  • 12,251
  • 8
  • 58
  • 92
PassionateDeveloper
  • 14,558
  • 34
  • 107
  • 176
  • 3
    @Jeff Oh no, he definitely wants to use `IndividualHumanBeingWhoDonated` – Josh Stodola Mar 18 '10 at 20:32
  • 7
    A donator is a connoisseur of donuts. – DRBlaise Mar 18 '10 at 20:41
  • 1
    Duplicates: http://stackoverflow.com/questions/1301822/how-to-sort-an-array-of-object-by-a-specific-field-in-c http://stackoverflow.com/questions/1812044/how-to-sort-an-array-of-objects-in-visual-c http://stackoverflow.com/questions/1211617/sort-an-array-of-strongly-typed-objects-based-on-a-property-of-the-object-c – Jørn Schou-Rode Mar 28 '10 at 09:38

7 Answers7

25

If you implement IComparable<Donator> You can do it like this:

public class Donator :IComparable<Donator>
{
  public string name { get; set; }
  public string comment { get; set; }
  public double amount { get; set; }

  public int CompareTo(Donator other)
  {
     return amount.CompareTo(other.amount);
  }
}

You can then call sort on whatever you want, say:

var donors = new List<Donator>();
//add donors
donors.Sort();

The .Sort() calls the CompareTo() method you implemented for sorting.

There's also the lambda alternative without IComparable<T>:

var donors = new List<Donator>();
//add donors
donors.Sort((a, b) => a.amount.CompareTo(b.amount));
Nick Craver
  • 623,446
  • 136
  • 1,297
  • 1,155
  • A class implementing IComparer is probably a better approach. –  Mar 18 '10 at 21:00
  • 2
    @eschneider - That is almost always overkill for something this simple. How would that be "better"? – Nick Craver Mar 18 '10 at 21:02
  • Chances are they will need to sort various ways. DonorAmountComparer, DonorLastNameComparer, DonorAmountThenLastNameComparer. –  Mar 18 '10 at 21:06
  • @eschneider - That's *completely* outside the question...but even if they needed to, it's still much more compact to do in a lambda. The decision to use a comparer would be personal preference, and no one I've worked with has opted for that in the past few years. – Nick Craver Mar 18 '10 at 21:11
  • I disagree, It's totally related. In most cases I agree with you, but in a case where you will probably need multiple sort orders, a comparer is the best approach. –  Mar 18 '10 at 21:20
  • @eschneider - Sure it's related, but it's *not the question* The question was: "How I can sort by Amount?" This does that in much less code and fewer classes than IComparer. Should we create an IComparer for Linq instead of using `.OrderBy()`? Why not?, it's the same argument. In .Net 1 you had only IComparer, in 2.0 they added something better, in 3.0 even better, why not take advantage of it? – Nick Craver Mar 18 '10 at 21:32
4

By implementing IComparable and then use Array.Sort.

public class Donator : IComparable {
    public string name;
    public string comment;
    public double amount;

    public int CompareTo(object obj) {
        // throws invalid cast exception if not of type Donator
        Donator otherDonator = (Donator) obj; 

        return this.amount.CompareTo(otherDonator.amount);
    }
}

Donator[] donators;  // this is your array
Array.Sort(donators); // after this donators is sorted
AxelEckenberger
  • 16,628
  • 3
  • 48
  • 70
4

You can also use delegates:

class Program
{
    static void Main(string[] args)
    {
        List<Donor> myDonors = new List<Donor>();
        // add stuff to your myDonors list...

        myDonors.Sort(delegate(Donor x, Donor y) { return x.amount.CompareTo(y.amount); });
    }
}

class Donor
{
    public string name;
    public string comment;
    public double amount;
}
IVlad
  • 43,099
  • 13
  • 111
  • 179
3

I always use the list generic, for example

List<Donator> MyList;

then I call MyList.Sort

MyList.Sort(delegate (Donator a, Donator b) {
   if (a.Amount < b.Amount) return -1;
   else if (a.Amount > b.Amount) return 1;
   else return 0; );
Jared Updike
  • 7,165
  • 8
  • 46
  • 72
2

You could use MyArray.OrderBy(n => n.Amount) providing you have included the System.Linq namespace.

Jeff Yates
  • 61,417
  • 20
  • 137
  • 189
Sandor Drieënhuizen
  • 6,310
  • 5
  • 37
  • 80
  • I tried myArray = myArray.orderby... error is:Fehler 1 Eine implizite Konvertierung vom Typ "System.Linq.IOrderedEnumerable" in "DongleDonatorSite.Donator[]" ist nicht möglich. – PassionateDeveloper Mar 18 '10 at 20:20
  • Use .ToArray() to turn the enumerable back into an array. – Alex J Mar 18 '10 at 20:24
  • You might want to add `.ToArray()` at the end or change the type of the variable you are assigning the result to. By the way, in many cases it is more practical (but not always when performance is an issue) to stop using arrays and start using a generic list. – Sandor Drieënhuizen Mar 18 '10 at 20:25
  • According to the OP he is using .Net 2.0 – AxelEckenberger Mar 18 '10 at 20:28
2

Here is a sort without having to implement an Interface. This is using a Generic List

    List<Donator> list = new List<Donator>();
    Donator don = new Donator("first", "works", 98.0);
    list.Add(don);
    don = new Donator("first", "works", 100.0);
    list.Add(don);
    don = new Donator("middle", "Yay", 101.1);
    list.Add(don);
    don = new Donator("last", "Last one", 99.9);
    list.Add(don);
    list.Sort(delegate(Donator d1, Donator d2){ return d1.amount.CompareTo(d2.amount); });
galford13x
  • 2,483
  • 4
  • 30
  • 39
0

Another way is to create a class that implements IComparer, then there is an overload to pass in the Comparer class.

http://msdn.microsoft.com/en-us/library/8ehhxeaf.aspx

This way you could have different classes for each specific sort needed. You could create one to sort by name, amount, or others.