使用LINQ将项目移动到列表顶部

qui*_*qui 77 c# linq sorting

有没有办法使用LINQ将id = 10的项目作为列表中的第一项?

Item A - id =5
Item B - id = 10
Item C - id =12
Item D - id =1

在这种情况下,我如何优雅地将项目C移动到我的List<T>收藏的顶部?

这是我现在最好的:

var allCountries = repository.GetCountries();
var topitem = allCountries.Single(x => x.id == 592);  
var finalList = new List<Country>();
finalList.Add(topitem);
finalList = finalList.Concat(allCountries.Where(x=> x.id != 592)).ToList();
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 138

除了已知的顶级商品之外,您想要订购什么?如果你不在乎,你可以这样做:

var query = allCountries.OrderBy(x => x.id != 592).ToList();
Run Code Online (Sandbox Code Playgroud)

基本上,"假"出现在"真实"之前......

不可否认,我不知道它在LINQ to SQL等中的作用.您可能需要阻止它在数据库中进行排序:

var query = allCountries.AsEnumerable()
                        .OrderBy(x => x.id != 592)
                        .ToList();
Run Code Online (Sandbox Code Playgroud)

  • +1谢谢乔恩.我想按名称订购,但保留id = 0的项目,所以我这样做:allCountries.OrderBy(x => x.id == 0?"00000":x.Name).ToList(); 性能不是问题,因为列表很小. (5认同)
  • 对于稍后查看代码的人来说,布尔值的排序可能并不明显"false,true".我会建议更详细的解决方案. (3认同)

Jar*_*Par 48

LINQ在查询集合,创建现有查询的预测或基于现有集合生成新查询方面非常强大.它不是一种内联重新排序现有集合的工具.对于那种类型的操作,最好使用hande的类型.

假设您的类型具有与以下类似的定义

class Item {
  public int Id { get; set; }
  ..
}
Run Code Online (Sandbox Code Playgroud)

然后尝试以下方法

List<Item> list = GetTheList();
var index = list.FindIndex(x => x.Id == 12);
var item = list[index];
list[index] = list[0];
list[0] = item;
Run Code Online (Sandbox Code Playgroud)

  • 对于错误处理,请注意您应该检查`FindIndex`结果值,如果在列表中找不到该项,则它为-1. (6认同)
  • +1适用于交换场景,我觉得'实际上需要旋转' (4认同)

Gri*_*zly 39

Linq通常在Enumerables上工作,因此现在基础类型不是集合.因此,为了将项目移到列表顶部,我建议使用类似的东西(如果您需要保留订单)

var idx = myList.FindIndex(x => x.id == 592);
var item = myList[idx];
myList.RemoveAt(idx);
myList.Insert(0, item);
Run Code Online (Sandbox Code Playgroud)

如果函数只返回IEnumerable,则可以使用该ToList()方法首先将其转换为List

如果不保留订单,只需交换位置0和位置idx的值即可


Nic*_*lum 31

var allCountries = repository.GetCountries();
allCountries.OrderByDescending(o => o.id == 12).ThenBy(o => o.id) 
Run Code Online (Sandbox Code Playgroud)

这将在列表顶部插入id = 12的对象,并将其余部分向下旋转,保留顺序.

  • @PhatWrat当然,所以如果你想避免你会说.ThenBy(o => o.name)或类似的东西 (3认同)
  • 应该是最上面的答案!谢谢 (2认同)

con*_*tor 9

这是您可能想要使用的扩展方法.它将与给定谓词匹配的元素移动到顶部,保留顺序.

public static IEnumerable<T> MoveToTop(IEnumerable<T> list, Func<T, bool> func) {
    return list.Where(func)
               .Concat(list.Where(item => !func(item)));
}
Run Code Online (Sandbox Code Playgroud)

在复杂性方面,我认为它会在集合上进行两次传递,使其成为O(n),就像插入/删除版本一样,但优于Jon Skeet的OrderBy建议.