我有一个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'。存在显式转换(您是否错过了演员?)
答案 0 :(得分:58)
假设您的列表已按升序排序
var index = TimeList.BinarySearch(dateTimeOffset);
if (index < 0) index = ~index;
TimeList.Insert(index, dateTimeOffset);
答案 1 :(得分:29)
边缘情况的@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 :(得分:10)
使用.NET 4,您可以使用新的SortedSet<T>
,否则您将无法使用键值集合SortedList
。
SortedSet<DateTimeOffset> TimeList = new SortedSet<DateTimeOffset>();
// add DateTimeOffsets here, they will be sorted initially
注意:SortedSet<T>
类不接受重复元素。如果item已经在set中,则此方法返回false并且不抛出异常。
如果允许重复,您可以使用List<DateTimeOffset>
并使用Sort
方法。
答案 3 :(得分:5)
修改LINQ,最后添加ToList():
ItemList = (from s in ItemList
orderby s.PublishDate descending
select s).ToList();
或者将已排序的列表分配给另一个变量
var sortedList = from s in ....
答案 4 :(得分: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;
答案 5 :(得分:1)
list.OrderBy(a => a.ColumnName).ToList();
答案 6 :(得分:1)
我很想在这里对两个建议进行基准测试,分别使用SortedSet类和基于List的二进制搜索插入。从我在.NET Core 3.1上的(非科学的)结果来看,似乎列表(较小的几百个)使用较少的内存,但是SortedSet在时间和内存上都开始获胜,而且该集合越大。
(项目是带有两个字段的小类实例,Guid和字符串名称)
50个项目:
| Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|-------------- |---------:|----------:|----------:|-------:|------:|------:|----------:|
| SortedSet | 5.617 μs | 0.0183 μs | 0.0153 μs | 0.3052 | - | - | 1.9 KB |
| SortedAddList | 5.634 μs | 0.0144 μs | 0.0135 μs | 0.1755 | - | - | 1.12 KB |
200个项目:
| Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|-------------- |---------:|---------:|---------:|-------:|------:|------:|----------:|
| SortedSet | 24.15 μs | 0.066 μs | 0.055 μs | 0.6409 | - | - | 4.11 KB |
| SortedAddList | 28.14 μs | 0.060 μs | 0.053 μs | 0.6714 | - | - | 4.16 KB |
1000个项目:
| Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|-------------- |---------:|--------:|--------:|-------:|------:|------:|----------:|
| SortedSet | 107.5 μs | 0.34 μs | 0.30 μs | 0.7324 | - | - | 4.73 KB |
| SortedAddList | 169.1 μs | 0.41 μs | 0.39 μs | 2.4414 | - | - | 16.21 KB |
答案 7 :(得分:0)
您可以在找到所需的索引后使用Insert(index,object)
。
答案 8 :(得分:0)
我带了@Noseratio's answer并将其与@ {Jeppe的here答案重新合并并合并 获取一个适用于集合的函数(我需要它用于Paths的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<T>.Create((x, y) => (x.Property < y.Property) ? -1 : (x.Property > 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);
}
}