views:

198

answers:

7

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?

+3  A: 

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
Obalix
He could also pass a lambda expression if he doesn't want to create a new class
Oskar Kjellin
Tried it, but how to sort really?
Kovu
No in .Net 2.0 he can't.
Obalix
@Kovu: see edit.
Obalix
+2  A: 

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

Sandor Drieënhuizen
I tried myArray = myArray.orderby... error is:Fehler 1 Eine implizite Konvertierung vom Typ "System.Linq.IOrderedEnumerable<DongleDonatorSite.Donator>" in "DongleDonatorSite.Donator[]" ist nicht möglich.
Kovu
Use .ToArray() to turn the enumerable back into an array.
Ilia Jerebtsov
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
According to the OP he is using .Net 2.0
Obalix
+16  A: 

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
A class implementing IComparer is probably a better approach.
eschneider
@eschneider - That is almost always overkill for something this simple. How would that be "better"?
Nick Craver
Chances are they will need to sort various ways.DonorAmountComparer, DonorLastNameComparer, DonorAmountThenLastNameComparer.
eschneider
@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
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.
eschneider
@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
A: 

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
This is the same as a.Amount.CompareTo(b.Amount)
Ruben
Right. In addition, with my method, you can then add additional logic to sort by Amount first, then, Name if Amount is the same, etc. CompareTo is simpler for this case, and my example would only be useful if you needed more interesting sorting logic.
Jared Updike
+2  A: 

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
+2  A: 

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
A: 

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.

eschneider