22 Stimmen

LINQ Nächstes Element in Liste

Ein Blick auf meine Frage HIER möchte ich nun die nächste Empfehlung Objekt (nach) demjenigen, das die Kriterien erfüllt.

Angenommen, ich habe Artikel 6 von 10 gefunden, dann möchte ich, dass die Abfrage stattdessen Artikel 7 zurückgibt.

Oder gibt es einen besseren Weg?

53voto

Jeremy Foster Punkte 4553

Das ist meine derzeit beste Methode:

MyList.SkipWhile(item => item.Name != "someName").Skip(1).FirstOrDefault()

Eine frühere Antwort verwendet Skip(1).Take(1) was funktioniert, aber eine Liste mit einem Ergebnis liefert. In meinem Fall (und vielleicht auch im Fall des Auftraggebers) suchen wir nach dem aktuellen Element. Also mein Code überspringt, bis es zu dem, das wir suchen (ein Wo würde eine Teilmenge zurückgeben, so dass wir keinen Zugriff auf das nächste Element haben würde), dann überspringt eine weitere und bekommt dann das Element.

17voto

Abdul Saboor Punkte 3809

Versuchen Sie dies


NEXT Item

MyList.SkipWhile(x => x != value).Skip(1).FirstOrDefault();

VORHERIGER Artikel Hinweis: Reverse() funktioniert nicht für LINQ to SQL

 var MyList2 = MyList.ToList();
 MyList2.Reverse();
 MyList2.SkipWhile(x => x != value).Skip(1).FirstOrDefault();

16voto

EMP Punkte 54832

Da Sie eine List<T> Objekt können Sie dessen FindIndex Methode anstelle von Where um den Index des ersten übereinstimmenden Eintrags und nicht den Eintrag selbst zu erhalten:

int index = recommendations.FindIndex(rp =>
                                            rp.Products.Any(p => p.Product.Code == "A") 
                                         && rp.Products.Any(p => p.Product.Code == "B")
                                      );

Sobald Sie den Index haben, können Sie das nächste Element oder das vorherige Element oder was immer Sie wollen, abrufen.

7voto

Jim Johnson Punkte 1053

Wie wäre es mit so etwas wie diesem:

public static class Extension
{
    public static T Next<T>(this IEnumerable<T> source, Func<T, bool> predicate)
    {
        bool flag = false;

        using (var enumerator = source.GetEnumerator())
        {
            while (enumerator.MoveNext())
            {
                if (flag) return enumerator.Current;

                if(predicate(enumerator.Current))
                {
                    flag = true;
                }
            }
        }
        return default(T);
    }
}

Sie könnten es dann wie bei Where aufrufen

Products.Next(x => x.Whatever);

1voto

Anthony Pegram Punkte 119149

Diese sollte es tun. Ich habe keinen speziellen Test dafür entwickelt.

var nextProducts = from item1 in recommendations.Select((rec, idx) => new { Rec = rec, Index = idx })
                    join item2 in recommendations.Select((rec, idx) => new { Rec = rec, Index = idx })
                    on item1.Index equals item2.Index - 1
                    where item1.Rec.Products.Any(p => p.Code == "A")
                    && item1.Rec.Products.Any(p => p.Code == "B")
                    select item2.Rec;

Wenn Sie beide Datensätze benötigen, könnte die Select-Anweisung wie folgt lauten

select new { MatchingItem = item1.Rec, NextItem = item2.Rec };

Aber dann müssten Sie eine Gruppierung vornehmen, um zu berücksichtigen, dass ein übereinstimmendes Element das letzte Element in der Liste ist (in diesem Fall gäbe es kein nächstes Element).

var nextProducts = from item1 in recommendations.Select((rec, idx) => new { Rec = rec, Index = idx })
                    join item2 in recommendations.Select((rec, idx) => new { Rec = rec, Index = idx })
                    on item1.Index equals item2.Index - 1
                    into groupjoin
                    from i2 in groupjoin.DefaultIfEmpty ()
                    where item1.Rec.Products.Any(p => p.Code == "A")
                    && item1.Rec.Products.Any(p => p.Code == "B")
                    select new { MatchingItem = item1.Rec, NextItem = i2 == null ? null : i2.Rec };

Der Code I hat Test war etwas Ähnliches mit einer Liste von Zeichenketten.

List<string> list = new List<string>() { "a", "b", "c", "a", "d", "a", "e" };

var query = from item1 in list.Select((s, idx) => new { Item = s, Index = idx })
            join item2 in list.Select((s, idx) => new { Item = s, Index = idx })
            on item1.Index equals item2.Index - 1
            where item1.Item == "a"
            select item2.Item;

Das ergibt b, d und e.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X