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

时间:2009-11-03 16:25:56

标签: 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();

11 个答案:

答案 0 :(得分:132)

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

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

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

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

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

答案 1 :(得分:46)

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

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

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;

答案 2 :(得分:37)

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

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

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

如果您不保留订单,只需交换位置0和位置idx

的值即可

答案 3 :(得分:29)

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

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

答案 4 :(得分:9)

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

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的OrderBy建议。

答案 5 :(得分:2)

你可以&#34;分组&#34;在两组中使用布尔键,然后对它们进行排序

var finalList= allCountries
                .GroupBy(x => x.id != 592)
                .OrderBy(g => g.Key)
                .SelectMany(g => g.OrderBy(x=> x.id ));

答案 6 :(得分:1)

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;
}

答案 7 :(得分:1)

有趣的是,您在尝试解决问题时找到的方法数量很多。

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);

答案 8 :(得分:1)

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

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

答案 9 :(得分:0)

还要检查是否找到了没有Exception的项目,例如:

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

答案 10 :(得分:0)

我写了一个静态扩展方法来做到这一点。请注意,这并不保留订单,只是将项目交换出来。如果你需要保留订单,你应该做一个旋转而不是简单的交换。

/// <summary>
/// Moves the item to the front of the list if it exists, if it does not it returns false
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="collection"></param>
/// <param name="predicate"></param>
/// <returns></returns>
public static bool MoveToFrontOfListWhere<T>(this List<T> collection, Func<T, bool> predicate)
{
    if (collection == null || collection.Count <= 0) return false;

    int index = -1;
    for (int i = 0; i < collection.Count; i++)
    {
        T element = collection.ElementAt(i);
        if (!predicate(element)) continue;
        index = i;
        break;
    }

    if (index == -1) return false;

    T item = collection[index];
    collection[index] = collection[0];
    collection[0] = item;
    return true;
}
相关问题