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

C# 从列表中获取优先级项,并将它们插入到给定位置c的同一列表中,c#,lambda,C#,Lambda,我有一个50个排序项目的列表,其中有几个项目是优先级项目,假设它们的标志设置为1 默认情况下,我必须首先显示基于日期的最新项目,但优先级项目应显示在一些“x”数量的记录之后。如下 索引0:项目 索引1:项目 索引2:优先级项从此位置插入优先级项 索引3:优先项目 索引4:优先项目 索引5:项目 索引6:项目 应插入优先级项的索引“x”是预定义的 为了实现这一点,我使用以下代码 这是我的50个分类项目 获取所有优先级项并将其存储在另一个列表中 从主列表中筛选出优先级项目 在给定位置插入主列表中的优

我有一个50个排序项目的列表,其中有几个项目是优先级项目,假设它们的标志设置为1

默认情况下,我必须首先显示基于日期的最新项目,但优先级项目应显示在一些“x”数量的记录之后。如下

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

应插入优先级项的索引“x”是预定义的

为了实现这一点,我使用以下代码

这是我的50个分类项目

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

从主列表中筛选出优先级项目

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

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

另外,考虑到记录数量从50个增加到100000个,在我执行许多操作时,性能是如何影响的

更新:如何使用IQueryable减少列表上的操作数

根据InsertRange上的文档:

此方法是On*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));

不过,我不确定列表的Concat、Skip和Take方法的速度有多快,但我敢打赌它们不会比On慢。

看起来您实际上要解决的问题只是对项目列表进行排序。如果是这种情况,则不需要删除优先级项并将其重新插入正确的索引,只需确定排序顺序函数。这样的事情应该行得通:

// 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根据您定义的原始需求,这也读得相当清楚

首先,定义我们将要排序到的bucket:为了清晰起见,我喜欢在这里使用enum,但也可以使用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);
}

10万仍然不算多。你测量过了吗?你知道你需要什么样的表现吗?我打赌输入和输出所花费的时间远远大于实际排序。您可以使用一个列表/数组,按照该顺序对它们进行排序。如果前50名已经被排序,你不能改变它,你可以在适当的地方做所有的事情,但是差别会非常小。你应该测量一下,有很多情况下On或O1可能比n不是很大的其他解决方案慢。是的,特别是在使用哈希集的解决方案上。不过,我不认为常数时间应该在列表中占据很高的位置。它有相当多的额外对象,Concat和Take正在创建迭代器和其他东西。谢谢你的解决方案。但是我将执行时间与前面提到的原始代码进行了比较,我注意到原始代码的执行时间更短。即使差异以毫秒为单位,此代码也需要2倍的时间。。
// 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);
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;
}
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);
}