2012-08-29 3 views
15

Может ли кто-нибудь научить меня, как вставлять элементы в список по порядку в C#?Как вставить элемент в список по порядку?

У меня есть список объектов DateTimeOffset, и я хочу вставить новые в список по порядку.

List<DateTimeOffset> TimeList = ... 
// determine the order before insert or add the new item 

Извините, вам нужно обновить свой вопрос.

List<customizedClass> ItemList = ... 
//customizedClass contains DateTimeOffset object and other strings, int, etc. 

ItemList.Sort(); // this won't work until set data comparison with DateTimeOffset 
ItemList.OrderBy(); // this won't work until set data comparison with DateTimeOffset 

Может кто-нибудь, пожалуйста, помогите мне поставить DateTimeOffset в качестве параметра .OrderBy()?

Я также попытался

ItemList = from s in ItemList 
      orderby s.PublishDate descending // .PublishDate is type DateTime 
      select s; 

Однако, он возвращает сообщение об ошибке,

Не может неявно преобразовать тип 'System.Linq.IOrderedEnumerable' до 'System.Collections.Gerneric.List'. Явное преобразование существует (вы пропали без вести броска?)

+4

Не можете ли вы отсортировать свой список при необходимости или использовать SortedList? –

+0

'Список ' есть * заказать' коллекция. Вы хотите * сортировать *? – adatapost

+1

Какой «порядок» вы говорите здесь? –

ответ

5

Измените свой LINQ, добавьте ToList() в конце:

ItemList = (from s in ItemList 
      orderby s.PublishDate descending 
      select s).ToList(); 

В качестве альтернативы присвоить отсортированный список в другой переменной

var sortedList = from s in .... 
1

Для вставки элемента к определенному индексу

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

DateTimeOffset dto; 

// Current time 
dto = DateTimeOffset.Now; 

//This will insert the item at first position 
TimeList.Insert(0,dto); 

//This will insert the item at last position 
TimeList.Add(dto); 

Для сортировки коллекции вы можете использовать LINQ:

//This will sort the collection in ascending order 
List<DateTimeOffset> SortedCollection=from dt in TimeList select dt order by dt; 
+2

Почему бы не отсортировать с использованием расширения '.OrderBy()' –

+0

Да, Ash Burlaczenko, что и мы можем сделать. Я использую писать большие запросы в linq. Вот почему я написал вышеупомянутый запрос, который был первой мыслью. Но я согласен с тобой. Благодарю. – techfun

+0

Нет перегрузки 'List .Add', который принимает индекс. Я думаю, вы имеете в виду ['Список .Insert'] (http://msdn.microsoft.com/en-us/library/sey5k5z4 (v = vs.100) .aspx). –

0

Вы можете использовать Insert(index,object) после нахождения нужного вам индекса.

+0

скажите, пожалуйста, порядок сортировки, чтобы написать больше – levi

46

Если предположить, что список уже отсортирован в порядке возрастания

var index = TimeList.BinarySearch(dateTimeOffset); 
if (index < 0) index = ~index; 
TimeList.Insert(index, dateTimeOffset); 
+3

Не могли бы вы объяснить свой код? Если они не знают, как вставлять в список, я сомневаюсь, что они будут знать, что делает '' index'. –

+0

@AshBurlaczenko, вы правы, но контекст вопроса, похоже, был изменен после ~ 1 часа, я ответил, и я слишком ленив для него. –

+12

** От MSDN **: Возвращаемое значение Указатель на нуль элемента в отсортированном списке , если элемент найден; в противном случае - отрицательное число, которое является поразрядным дополнением к индексу следующего элемента, который больше элемента или, если нет более крупного элемента, поразрядное дополнение к Count. –

7

С .NET 4 вы можете использовать новый SortedSet<T> в противном случае вы застряли коллекции ключ-значение SortedList.

SortedSet<DateTimeOffset> TimeList = new SortedSet<DateTimeOffset>(); 
// add DateTimeOffsets here, they will be sorted initially 

Примечание: SortedSet<T> класс не принимает повторяющихся элементов. Если элемент уже установлен, этот метод возвращает false и не генерирует исключение.

Если дубликаты разрешены, вы можете использовать List<DateTimeOffset> и использовать его метод Sort.

19

слегка улучшенный вариант @L.B.'s answer для краевых случаев:

public static class ListExt 
{ 
    public static void AddSorted<T>(this List<T> @this, T item) where T: IComparable<T> 
    { 
     if (@this.Count == 0) 
     { 
      @this.Add(item); 
      return; 
     } 
     if (@this[@this.Count-1].CompareTo(item) <= 0) 
     { 
      @this.Add(item); 
      return; 
     } 
     if (@this[0].CompareTo(item) >= 0) 
     { 
      @this.Insert(0, item); 
      return; 
     } 
     int index = @this.BinarySearch(item); 
     if (index < 0) 
      index = ~index; 
     @this.Insert(index, item); 
    } 
} 
+2

Этот сниппет только что дал мне повышение производительности на 1000% в случае, когда я не мог использовать SortedSet <> и должен был повторно .Sort() List. – Nebu

1

очень простой, после добавления данных в лит ул

list.OrderBy(a => a.ColumnName).ToList(); 
0

Я взял @Noseratio's answer и переработан и соединил его с @ ответ Jeppe от here , чтобы получить функцию, которая работает для коллекций (я нуждался для ObservableCollection трактов) и типа, который не реализует IComparable.

/// <summary> 
    /// Inserts a new value into a sorted collection. 
    /// </summary> 
    /// <typeparam name="T">The type of collection values, where the type implements IComparable of itself</typeparam> 
    /// <param name="collection">The source collection</param> 
    /// <param name="item">The item being inserted</param> 
    public static void InsertSorted<T>(this Collection<T> collection, T item) where T : IComparable<T> 
    { 
     InsertSorted(collection, item, Comparer<T>.Create((x, y) => x.CompareTo(y))); 
    } 

    /// <summary> 
    /// Inserts a new value into a sorted collection. 
    /// </summary> 
    /// <typeparam name="T">The type of collection values</typeparam> 
    /// <param name="collection">The source collection</param> 
    /// <param name="item">The item being inserted</param> 
    /// <param name="ComparerFunction">An IComparer to comparer T values, e.g. Comparer&lt;T&gt;.Create((x, y) =&gt; (x.Property &lt; y.Property) ? -1 : (x.Property &gt; y.Property) ? 1 : 0)</param> 
    public static void InsertSorted<T>(this Collection<T> collection, T item, IComparer<T> ComparerFunction) 
    { 
     if (collection.Count == 0) 
     { 
     // Simple add 
     collection.Add(item); 
     } 
     else if (ComparerFunction.Compare(item, collection[collection.Count - 1]) >= 0) 
     { 
     // Add to the end as the item being added is greater than the last item by comparison. 
     collection.Add(item); 
     } 
     else if (ComparerFunction.Compare(item, collection[0]) <= 0) 
     { 
     // Add to the front as the item being added is less than the first item by comparison. 
     collection.Insert(0, item); 
     } 
     else 
     { 
     // Otherwise, search for the place to insert. 
     int index = Array.BinarySearch(collection.ToArray(), item, ComparerFunction); 
     if (index < 0) 
     { 
      // The zero-based index of item if item is found; 
      // otherwise, a negative number that is the bitwise complement of the index of the next element that is larger than item or, if there is no larger element, the bitwise complement of Count. 
      index = ~index; 
     } 
     collection.Insert(index, item); 
     } 
    } 
+1

'collection.ToArray()' создаст другую коллекцию, которая более дорога, чем линейный поиск, т. Е. 'Collection.IndexOf()' –

Смежные вопросы