使用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();