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

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

项目A  -  id = 5
项目B  -  id = 10
项目C  -  id = 12
项目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(); 

LINQ在查询集合方面很强大,可以在现有查询上创build投影或基于现有集合生成新的查询。 这并不意味着作为一个工具来重新排列现有的集合。 对于这种types的操作,最好使用汉德的types。

假设你有一个类似于下面类似定义的types

 class Item { public int Id { get; set; } .. } 

然后尝试以下

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

除了已知的顶级项目,你想要点什么? 如果你不在乎,你可以这样做:

 var query = allCountries.OrderBy(x => x.id != 592).ToList(); 

基本上,“假”在“真”之前

无可否认,我不知道这是什么在LINQ to SQL等。您可能需要停止执行数据库中的sorting:

 var query = allCountries.AsEnumerable() .OrderBy(x => x.id != 592) .ToList(); 

Linq通常在Enumerables上工作,所以现在不会是基础types是一个集合。 所以要移动列表顶部的项目,我会build议使用类似的东西(如果你需要保持顺序)

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

如果你的函数只返回一个IEnumerable,你可以使用ToList()方法先将它转换成List

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

 var allCountries = repository.GetCountries(); allCountries.OrderByDescending(o => o.id == 12).ThenBy(o => o.id) 

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

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

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

就复杂性而言,我认为它会对集合进行两次传递,使其成为O(n),就像插入/删除版本一样,但比Jon Skeet的OrderBybuild议更好。

你可以用布尔键在两个组中“分组”,然后对它们进行sorting

 var finalList= allCountries .GroupBy(x => x.id != 592) .OrderBy(g => g.Key) .SelectMany(g => g.OrderBy(x=> x.id )); 
 public static IEnumerable<T> ServeFirst<T>(this IEnumerable<T> source, Predicate<T> p) { var list = new List<T>(); foreach (var s in source) { if (p(s)) yield return s; else list.Add(s); } foreach (var s in list) yield return s; } 

当你试图解决问题的时候,你会发现很多有趣的方法。

 var service = AutogateProcessorService.GetInstance(); var allConfigs = service.GetAll(); allConfigs = allConfigs.OrderBy(c => c.ThreadDescription).ToList(); var systemQueue = allConfigs.First(c => c.AcquirerId == 0); allConfigs.Remove(systemQueue); allConfigs.Insert(0, systemQueue); 

我知道这是一个古老的问题,但我这样做

 class Program { static void Main(string[] args) { var numbers = new int[] { 5, 10, 12, 1 }; var ordered = numbers.OrderBy(num => num != 10 ? num : -1); foreach (var num in ordered) { Console.WriteLine("number is {0}", num); } Console.ReadLine(); } } 

这打印:

数字是10
数字是1
数字是5
数字是12

还要检查项目是否被发现没有例外,如下所示:

 var allCountries = repository.GetCountries(); var lookup = allCountries.ToLookup(x => x.id == 592); var finalList = lookup[true].Concat(looup[false]).ToList(); if ( lookup[true].Count != 1 ) YouAreInTrouble();