Gibt es eine Möglichkeit, ein Element mit der Bezeichnung id = 10 als erstes Element in einer Liste mithilfe von LINQ zu verschieben?
Punkt A - id = 5 Punkt B - ID = 10 Punkt C - id = 12 Punkt D - id = 1
Wie kann ich in diesem Fall Artikel C elegant an den Anfang meiner List<T>
Sammlung verschieben?
Dies ist das Beste, was ich derzeit habe:
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();
Antworten:
LINQ ist stark darin, Sammlungen abzufragen, Projektionen über vorhandene Abfragen zu erstellen oder neue Abfragen basierend auf vorhandenen Sammlungen zu generieren. Es ist nicht als Werkzeug gedacht, um vorhandene Sammlungen inline neu zu ordnen. Für diese Art von Operation ist es am besten, den Typ bei Hand zu verwenden.
Angenommen, Sie haben einen Typ mit einer ähnlichen Definition wie unten
class Item { public int Id { get; set; } .. }
Versuchen Sie dann Folgendes
List<Item> list = GetTheList(); var index = list.FindIndex(x => x.Id == 12); var item = list[index]; list[index] = list[0]; list[0] = item;
quelle
FindIndex
Ergebniswert überprüfen sollten. Er ist -1, wenn das Element nicht in der Liste gefunden wird.Womit möchten Sie außer dem bekannten Top-Artikel bestellen? Wenn es Sie nicht interessiert, können Sie dies tun:
var query = allCountries.OrderBy(x => x.id != 592).ToList();
Grundsätzlich kommt "falsch" vor "wahr" ...
Zugegeben, ich weiß nicht, was dies in LINQ to SQL usw. bewirkt. Möglicherweise müssen Sie verhindern, dass die Bestellung in der Datenbank ausgeführt wird:
var query = allCountries.AsEnumerable() .OrderBy(x => x.id != 592) .ToList();
quelle
Name
in einer kleinen Liste oben oder Index 0 in LINQ to Entities, und es hat den Trick gemacht Danke +1.db.Systms.Where(s => s.IsActive == true).OrderBy(x => x.SystemName != "Portal Administration").ToList();
Linq arbeitet im Allgemeinen mit Enumerables, sodass der zugrunde liegende Typ jetzt keine Sammlung mehr ist. Um den Artikel ganz oben auf die Liste zu setzen, würde ich empfehlen, etwas wie (wenn Sie die Reihenfolge beibehalten müssen) zu verwenden.
var idx = myList.FindIndex(x => x.id == 592); var item = myList[idx]; myList.RemoveAt(idx); myList.Insert(0, item);
Wenn Ihre Funktion nur eine IEnumerable zurückgibt, können Sie diese
ToList()
Methode verwenden, um sie zuerst in eine Liste zu konvertierenWenn Sie die Reihenfolge nicht beibehalten, können Sie einfach die Werte an Position 0 und Position idx tauschen
quelle
var allCountries = repository.GetCountries(); allCountries.OrderByDescending(o => o.id == 12).ThenBy(o => o.id)
Dadurch wird das Objekt mit der ID = 12 oben in der Liste eingefügt und der Rest nach unten gedreht, wobei die Reihenfolge beibehalten wird.
quelle
Hier ist eine Erweiterungsmethode, die Sie möglicherweise verwenden möchten. Es verschiebt die Elemente, die dem angegebenen Prädikat entsprechen, nach oben, wobei die Reihenfolge beibehalten wird.
public static IEnumerable<T> MoveToTop(IEnumerable<T> list, Func<T, bool> func) { return list.Where(func) .Concat(list.Where(item => !func(item))); }
In Bezug auf die Komplexität denke ich, dass es zwei Durchgänge für die Sammlung machen würde, was sie zu O (n) macht, wie die Version zum Einfügen / Entfernen, aber besser als Jon Skeets OrderBy-Vorschlag.
quelle
Sie können mit dem Booleschen Schlüssel in zwei Gruppen "gruppieren" und diese dann sortieren
var finalList= allCountries .GroupBy(x => x.id != 592) .OrderBy(g => g.Key) .SelectMany(g => g.OrderBy(x=> x.id ));
quelle
Ich weiß, dass dies eine alte Frage ist, aber ich habe es so gemacht
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(); } }
dies druckt:
Nummer ist 10
Nummer ist 1
Nummer ist 5
Nummer ist 12
quelle
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; }
quelle
Es ist interessant, wie viele Ansätze Sie finden, wenn Sie versuchen, ein Problem zu lösen.
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);
quelle
Um auch zu überprüfen, ob der Artikel ohne Ausnahme gefunden wurde, gehen Sie wie folgt vor:
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();
quelle
Ich habe dazu eine statische Erweiterungsmethode geschrieben. Beachten Sie, dass dadurch die Reihenfolge nicht erhalten bleibt, sondern der Artikel einfach ausgetauscht wird. Wenn Sie die Reihenfolge beibehalten möchten, sollten Sie eine Drehung und keinen einfachen Tausch durchführen.
/// <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; }
quelle