2009-05-29 3 views
36
public class CarSpecs 
{ 
    public String CarName { get; set; } 

    public String CarMaker { get; set; } 

    public DateTime CreationDate { get; set; } 
} 

Это список, и я пытаюсь найти эффективный способ сортировки этого списка. Список CarList, содержащий 6 (или любое целое количество) автомобилей, по дате изготовления автомобиля. Я собирался сделать Bubble, но будет ли это работать? Любая помощь?Сортировка списка объектов в C#

Благодаря

+2

(не по теме) Autoproperties любой? –

+2

@Peter Lillevold - это была моя ОЧЕНЬ ПЕРВАЯ МЫСЛЬ. Я не написал «нормальное» свойство (подкрепленное локальной переменной, которую я написал) в течение некоторого времени. (Просто так майк знает: «public DateTime CreationDate {get; set;}» является законным в C# 3.0) – Pwninstein

+1

Хм, я ударил Alt-Enter в редакторе, чтобы преобразовать ReSharper в autoproperty ... но ничего не произошло. ohwell, считать грубым редактировать образцы кода, подобные этому? хотя немного рискованно в этом случае, так как мы не уверены, что @Mike использует C# 3.0 или нет. –

ответ

83

List<T> класс делает это тривиально для вас, так как она содержит Sort method. (Он использует алгоритм QuickSort, а не Bubble Sort, который, как правило, лучше в любом случае.) Еще лучше, он имеет перегрузку, которая принимает аргумент Comparison<T>, что означает, что вы можете передать выражение лямбда и сделать вещи очень простыми.

Попробуйте это:

CarList.Sort((x, y) => DateTime.Compare(x.CreationDate, y.CreationDate)); 
+1

Я думаю, он хочет сортировать сначала Car, затем Make, затем по дате ... –

+1

@Eoin: Это немного двусмысленно, я признаю. Я все еще верю, что он имел в виду «Дата изготовления автомобиля» как одно свойство, ссылаясь на «CreationDate». – Noldorin

+3

+1 из-за использования лямбда-выражений! –

16

Наилучший подход заключается в реализации либо IComparable или IComparable<T>, а затем вызвать List<T>.Sort(). Это сделает всю сложную работу по сортировке для вас.

+2

+1 чтобы противостоять бессмысленному -1, что кто-то еще сделал. Ничего плохого в этом предположении. – tomfanning

+3

Пример кода был бы приятным. – Peter

1

Если вы после эффективного способа сортировки, я бы посоветовал не использовать сортировку пузырьков и вместо этого перейти на быстрый вид. Эта страница дает достаточно хорошее объяснение алгоритма:

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

удачи!

55

Вы можете использовать LINQ:

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

EDIT: При таком подходе, его легко добавить на более сортировки столбцов:

listOfCars.OrderBy(x => x.CreationDate).ThenBy(x => x.Make).ThenBy(x => x.Whatever); 
+4

Да, это тоже сработает. Однако производительность будет хуже, чем при использовании List.Sort, поскольку она основана на LINQ (то есть IEnumerable объектов), хотя из первоначального вопроса, который, казалось бы, не был бы большой проблемой. Единственное реальное отличие заключается в том, что это возвращает новый объект (который затем вам нужно преобразовать в список, используя «ToList()»), тогда как List.Sort выполняет сортировку в текущем экземпляре. – Noldorin

+0

@Noldorin. Да, ваше предложение использовать List.Sort (comparisson) может быть быстрее ... –

+0

Спасибо, я не знал о ThenBy. –

14

Другим вариантом было бы использовать собственный компаратор:

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 
    } 
} 

который вы называете так:

yourCarlist.Sort(new CarNameComparer()); 

Примечание: Я не скомпилировать этот код, так что вы, возможно, придется удалить опечатка в

Edit: модифицирована так, компаратор сравнивает на CreationDate с просьбой о котором идет речь.

+0

Ничего плохого в этом, но гораздо больше, чем вам нужно! – Noldorin

+0

Изменен мой ответ, чтобы он соответствовал вашему комментарию. Это путь, чтобы иметь полный контроль над сортировкой. Но это может быть слишком много в этом случае :-) – Peter

+0

Это хороший ответ, так как он переводится на другие языки. Когда вы используете выражения linq или лямбда, вы попадаете в C#. _ (хотя я очень соблазняюсь не делать многое прямо сейчас и просто использовать 1 строку лямбда:) _ – Bitterblue

1

Я бы не писать свой собственный алгоритм сортировки, но если вы все равно собираетесь, взглянуть на http://www.sorting-algorithms.com/ для некоторых comparrisons различных алгоритмов сортировки ...

6

Я бы просто использовать построить в list.sort метод. Он использует алгоритм QuickSort, который в среднем работает в O (n log n).

Этот код должен работать на вас, я изменяю ваши свойства на автоматические свойства и задает статический метод CompareCarSpecs, который использует уже существующий метод DateTime.CompareTo.

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); 
    } 
} 

Надеюсь, это поможет.

+0

Это хорошее решение если у вас нет доступных C# 3.0 (т. е. нет lambdas). – Noldorin

3

Внесение некоторых частей, упомянутых здесь вместе. Это компилируется и работает в C# 4.x и VS2010. Я тестировал с помощью WinForm. Поэтому добавьте метод к WinFormMain(). Вам понадобятся сборники System.Linq и System.Generic.Collection.

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; } 
} 
Смежные вопросы