簡體   English   中英

使用LINQ將項目移動到列表頂部

[英]Use LINQ to move item to top of list

有沒有辦法使用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();

除了已知的頂級商品之外,您想要訂購什么? 如果你不在乎,你可以這樣做:

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

基本上,“假”出現在“真實”之前......

不可否認,我不知道它在LINQ to SQL等中的作用。您可能需要阻止它在數據庫中進行排序:

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

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;

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的值即可

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

您可以使用布爾鍵在兩組中“分組”,然后對它們進行排序

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

要檢查是否找到了沒有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();

我寫了一個靜態擴展方法來做到這一點。 請注意,這不會保留訂單,只需將項目交換出來即可。 如果您需要保留訂單,則應該執行旋轉而不是簡單的交換。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM