从列表中获取优先级项,并将它们插入到给定位置 C# 的同一列表中



我有一个包含 50 个排序项目的列表(比如说(,其中很少有项目是优先级项目(假设它们的标志设置为 1(。

默认情况下,我必须首先显示最新项目(基于日期(,但优先级项目应该出现在一些"x"条记录之后。像下面一样

索引 0:项目索引 1:项目索引 2:优先级项目(从此位置插入优先级项目(
索引 3:优先级项目索引 4:优先级项目索引 5:项目索引 6:项目




应插入优先级项的索引"x"是预定义的。

为此,我使用以下代码

这些是我的 50 个排序项目

var list= getMyTop50SortedItems();

获取所有优先级项目并将其存储在另一个列表中

var priorityItems = list.Where(x => x.flag == 1).ToList();

从主列表中过滤掉优先级项目

list.RemoveAll(x => z.flag == 1);

主列表中的给定位置插入优先级项目

list.InsertRange(1, priorityRecords);

这个过程正确地完成了工作,并给了我预期的结果。但不确定这是否是正确的方法,或者是否有更好的方法(考虑到性能(? 请提供您的建议。

此外,考虑到记录数从 50 增加到 100000(任意数字(,当我正在执行许多操作(过滤、删除、插入(时,性能如何受到影响。

更新:如何使用IQueryable来减少列表中的操作数量。

根据InsertRange的文档:

此方法是一个 O(n * m( 操作,其中 n 是 元素要添加,m 是计数。

n*m 不是很好,所以我会使用 LINQ 的Concat方法从三个较小的列表创建一个全新的列表,而不是修改现有的列表。

var allItems = getMyTop50();
var topPriorityItems = list.Where(x => x.flag == 1).ToList();
var topNonPriorityItems = list.Where(x => x.flag != 1).ToList();
var result = topNonPriorityItems
.Take(constant)
.Concat(topPriorityItems)
.Concat(topNonPriorityItems.Skip(constant));

我不确定List<T>ConcatSkipTake方法有多快,但我敢打赌它们并不比O(n(慢。

似乎您实际要解决的问题只是对项目列表进行排序。如果是这种情况,您无需担心删除优先级项目并将它们重新插入正确的索引,您只需要弄清楚您的排序排序函数。这样的事情应该有效:

// Set "x" to be whatever you want based on your requirements --
// this is the number of items that will precede the "priority" items in the
// sorted list
var x = 3;
var sortedList = list
.Select((item, index) => Tuple.Create(item, index))
.OrderBy(item => {
// If the original position of the item is below whatever you've 
// defined "x" to be, then keep the original position
if (item.Item2 < x) {
return item.Item2;
} 
// Otherwise, ensure that "priority" items appear first
return item.Item1.flag == 1 ? x + item.Item2 : list.Count + x + item.Item2;
}).Select(item => item.Item1);

您可能需要根据您要执行的操作稍微调整一下,但这似乎比从多个列表中删除/插入要简单得多。

编辑:忘记了.OrderBy不提供提供项目原始索引的重载;更新了答案以将项目包装在包含原始索引的元组中。不像原始答案那么干净,但它应该仍然有效。

这可以使用 linq-to-对象的原始集合的单个枚举来完成。IMO 根据您定义的原始要求,这也读得很清楚。

首先,定义我们将要分类的"桶":为了清楚起见,我喜欢在这里使用枚举,但您也可以只使用 int。

enum SortBucket
{
RecentItems = 0,
PriorityItems = 1,
Rest = 2,
}

然后,我们将定义特定项目将"存储桶"排序到哪个逻辑:

private static SortBucket GetBucket(Item item, int position, int recentItemCount)
{
if (position <= recentItemCount)
{
return SortBucket.RecentItems;
}
return item.IsPriority ? SortBucket.PriorityItems : SortBucket.Rest;
}

然后是一个相当简单的 linq-to-objects 语句,首先对我们定义的存储桶进行排序,然后按原始位置排序。编写为扩展方法:

static IEnumerable<Item> PrioritySort(this IEnumerable<Item> items, int recentItemCount)
{
return items
.Select((item, originalPosition) => new { item, originalPosition }) 
.OrderBy(o => GetBucket(o.item, o.originalPosition, recentItemCount))
.ThenBy(o => o.originalPosition)
.Select(o => o.item);
}

最新更新