web-dev-qa-db-fra.com

Tri d'une liste d'objets en C #

public class CarSpecs
{
  public String CarName { get; set; }

  public String CarMaker { get; set; }

  public DateTime CreationDate { get; set; }
}

Ceci est une liste et j'essaie de trouver un moyen efficace de trier cette liste. Liste CarList, contenant 6 voitures (ou un nombre entier), par date de construction de la voiture. J'allais faire le tri à bulles, mais ça va marcher? De l'aide?

Merci

37
Mike Gallager

La classe List<T> rend ceci trivial pour vous, car il contient une méthode Sort . (Il utilise l'algorithme QuickSort, et non Bubble Sort, qui est généralement meilleur de toute façon.) Mieux encore, il a une surcharge qui prend un argument Comparison<T>, ce qui signifie que vous pouvez passer une expression lambda et rendre les choses très simples.

Essaye ça:

CarList.Sort((x, y) => DateTime.Compare(x.CreationDate, y.CreationDate));
85
Noldorin

Vous pouvez utiliser LINQ:

listOfCars.OrderBy(x => x.CreationDate);

EDIT: Avec cette approche, il est facile d’ajouter plusieurs colonnes de tri:

listOfCars.OrderBy(x => x.CreationDate).ThenBy(x => x.Make).ThenBy(x => x.Whatever);
56
Arjan Einbu

La meilleure approche consiste à implémenter soit IComparable ou IComparable<T> , puis appelez List<T>.Sort() . Cela fera tout le travail difficile du tri pour vous.

16
Andy

Une autre option consisterait à utiliser un comparateur personnalisé:

using System;
using System.Collections.Generic;
using System.Text;

namespace Yournamespace
{
   class CarNameComparer : IComparer<Car>
   {
      #region IComparer<Car> Members

      public int Compare(Car car1, Car car2)
      {
         int returnValue = 1;
         if (car1 != null && car2 == null)
         {
            returnValue = 0;
         }
         else if (car1 == null && car2 != null)
         {
            returnValue = 0;
         }
         else if (car1 != null && car2 != null)
         {
            if (car1.CreationDate.Equals(car2.CreationDate))
            {
               returnValue = car1.Name.CompareTo(car2.Name);
            }
            else
            {
               returnValue = car2.CreationDate.CompareTo(car1.CreationDate);
            }
         }
         return returnValue;
      }

      #endregion
   }
}

que vous appelez comme ceci:

yourCarlist.Sort(new CarNameComparer());

Note: Je n'ai pas compilé ce code, donc vous devrez peut-être enlever les fautes de frappe

Edit: modifié pour que le comparateur compare la date de création demandée dans la question.

14
Peter

Je voudrais juste utiliser la méthode de construction dans List.Sort. Il utilise l'algorithme QuickSort qui s'exécute en moyenne dans O (n log n).

Ce code doit fonctionner pour vous, je modifie vos propriétés en propriétés automatiques et définit une méthode statique CompareCarSpecs qui utilise uniquement la méthode DateTime.CompareTo déjà existante.

class Program
{
    static void Main(string[] args)
    {
        List<CarSpecs> cars = new List<CarSpecs>();
        cars.Sort(CarSpecs.CompareCarSpecs);
    }
}

public class CarSpecs
{
    public string CarName { get; set; }
    public string CarMaker { get; set; }
    public DateTime CreationDate { get; set; }

    public static int CompareCarSpecs(CarSpecs x, CarSpecs y)
    {
        return x.CreationDate.CompareTo(y.CreationDate);
    }
}

J'espère que cela t'aides.

6
Egil Hansen

Assembler certaines des pièces mentionnées ici. Cela compile et fonctionne en C # 4.x et VS2010. J'ai testé avec une WinForm. Ajoutez donc la méthode à la WinFormMain(). Vous aurez au moins besoin des assemblys System.Linq et System.Generic.Collections. 

    private void SortCars()
    {
        List<CarSpecs> cars = new List<CarSpecs>();
        List<CarSpecs> carsSorted = new List<CarSpecs>();

        cars.Add(new CarSpecs
        {
            CarName = "Y50",
            CarMaker = "Ford",
            CreationDate = new DateTime(2011, 4, 1),
        });

        cars.Add(new CarSpecs
        {
            CarName = "X25",
            CarMaker = "Volvo",
            CreationDate = new DateTime(2012, 3, 1),
        });

        cars.Add(new CarSpecs
        {
            CarName = "Z75",
            CarMaker = "Datsun",
            CreationDate = new DateTime(2010, 5, 1),
        });

        //More Comprehensive if needed  
        //cars.OrderBy(x => x.CreationDate).ThenBy(x => x.CarMaker).ThenBy(x => x.CarName);

        carsSorted.AddRange(cars.OrderBy(x => x.CreationDate));

        foreach (CarSpecs caritm in carsSorted)
        {
            MessageBox.Show("Name: " +caritm.CarName 
                + "\r\nMaker: " +caritm.CarMaker
                + "\r\nCreationDate: " +caritm.CreationDate);
        }
    }
}

public class CarSpecs
{
    public string CarName { get; set; }
    public string CarMaker { get; set; }
    public DateTime CreationDate { get; set; }
} 
3
dpminusa

Si vous recherchez un moyen de tri efficace, je vous déconseille d'utiliser le tri à bulles et optez plutôt pour un tri rapide. Cette page fournit une assez bonne explication de l'algorithme:

http://www.devhood.com/Tutorials/tutorial_details.aspx?tutorial_id=574

Bonne chance!

1
Mia Clarke

J'éviterais d'écrire mon propre algorithme de tri, mais si vous y allez quand même, jetez un coup d'œil à http://www.sorting-algorithms.com/ pour des comparaisons de différents algorithmes de tri ...

1
Arjan Einbu

Si vous utilisez 2.0, la discussion suivante peut être utile: Liste C # <> Trier par x puis y

1
Byron Ross

Si vous utilisez des délégués (également appelés méthodes anonymes), vous ne devrez pas implémenter d'interface IComparer/IComparable.

public static void Main(string[] args)
    {


      List<CarSpecs> list = new List<CarSpecs>();

      list.Add(new CarSpecs("Focus", "Ford", new DateTime(2010,1, 2));
      list.Add(new CarSpecs("Prius", "Toyota", new DateTime(2012,3, 3));
      list.Add(new CarSpecs("Ram", "Dodge", new DateTime(2013, 10, 6));



        list.Sort(delegate (CarSpecs first, CarSpecs second)
        {
            int returnValue = 1;
            if((first != null & second != null))
            {
                if (first.CarName.Equals(second.CarName))
                {
                    if (first.CarMaker.Equals(second.CarMaker))
                    {
                    returnValue = first.CreationDate.CompareTo(second.CreationDate);
                    }
                    else
                    {
                    returnValue = first.CarMaker.CompareTo(second.CarMaker);
                    }
                }
                else
                {
                    returnValue = first.CarName.CompareTo(second.CarName);
                }
            }
            return returnValue;
        });

    }
0
Mark Woodard