Ich habe das geschrieben:
public static class EnumerableExtensions
{
public static int IndexOf<T>(this IEnumerable<T> obj, T value)
{
return obj
.Select((a, i) => (a.Equals(value)) ? i : -1)
.Max();
}
public static int IndexOf<T>(this IEnumerable<T> obj, T value
, IEqualityComparer<T> comparer)
{
return obj
.Select((a, i) => (comparer.Equals(a, value)) ? i : -1)
.Max();
}
}
Aber ich weiß nicht, ob es das schon gibt, oder?
Max
Ansatz ist, dass a: es weiter sucht und b: es den letzten Index zurückgibt, wenn es Duplikate gibt (Leute erwarten normalerweise den ersten Index)ToList()/FindIndex()
TrickAntworten:
Der springende Punkt beim Herausgeben von Dingen als IEnumerable ist, dass Sie den Inhalt träge durchlaufen können. Als solches ist es nicht wirklich ein Konzept eines Index. Was Sie tun, macht für eine IEnumerable wirklich keinen Sinn. Wenn Sie etwas benötigen, das den Zugriff per Index unterstützt, fügen Sie es in eine aktuelle Liste oder Sammlung ein.
quelle
IEnumerable<>
. Ich kaufe nicht das ganze Dogma "Du solltest das tun".IEnumerable
dannEnumerable.ElementAt
würde nicht existieren.IndexOf
ist einfach das Gegenteil - jedes Argument dagegen muss gleichermaßen geltenElementAt
.Ich würde die Weisheit in Frage stellen, aber vielleicht:
(Verwenden
EqualityComparer<T>.Default
, um!=
bei Bedarf zu emulieren ) - aber Sie müssen darauf achten, -1 zurückzugeben, wenn es nicht gefunden wird ... also machen Sie es vielleicht einfach den langen Wegquelle
TakeWhile
ist schlau! Beachten Sie jedoch, dass dies zurückgegeben wird,Count
wenn kein Element vorhanden ist, was eine Abweichung vom Standardverhalten darstellt.Ich würde es so implementieren:
quelle
==
könnte Arbeit brauchen?KVP<T, int?>
(nullable index)IList<T>
, um festzustellen, ob obj implementiert ist, und wenn ja, die IndexOf-Methode zu verwenden, nur für den Fall, dass eine typspezifische Optimierung vorliegt.Die Art und Weise, wie ich das derzeit mache, ist etwas kürzer als die bereits vorgeschlagenen und ergibt, soweit ich das beurteilen kann, das gewünschte Ergebnis:
Es ist ein bisschen klobig, aber es macht den Job und ist ziemlich prägnant.
quelle
Der beste Weg, um die Position zu erfassen, ist:
FindIndex
Diese Funktion ist nur für verfügbarList<>
Beispiel
Wenn Sie einen Enumerator oder ein Array haben, verwenden Sie diese Methode
oder
quelle
Ich denke, die beste Option ist, Folgendes zu implementieren:
Das anonyme Objekt wird ebenfalls nicht erstellt
quelle
Ein bisschen spät im Spiel, ich weiß ... aber das habe ich kürzlich getan. Es unterscheidet sich geringfügig von Ihrem, ermöglicht es dem Programmierer jedoch, zu bestimmen, wie die Gleichstellungsoperation aussehen soll (Prädikat). Was ich sehr nützlich finde, wenn ich mich mit verschiedenen Typen befasse, da ich dann eine generische Methode habe, dies unabhängig vom Objekttyp und dem
<T>
eingebauten Gleichheitsoperator zu tun .Es hat auch einen sehr sehr kleinen Speicherbedarf und ist sehr, sehr schnell / effizient ... wenn Sie sich dafür interessieren.
Schlimmer noch, Sie fügen dies einfach Ihrer Liste der Erweiterungen hinzu.
Wie auch immer ... hier ist es.
Hoffentlich hilft das jemandem.
quelle
GetEnumerator
undMoveNext
nicht nur einforeach
?foreach
Anruf wirdDispose
auf dem enumerator wenn es implementiertIDisposable
. (Siehe stackoverflow.com/questions/4982396/… ) Da der Code in dieser Antwort nicht weiß, ob das Ergebnis des AufrufsGetEnumerator
verfügbar ist oder nicht, sollte er dasselbe tun. Zu diesem Zeitpunkt bin ich mir noch nicht sicher, ob es einen Perf-Vorteil gibt, obwohl es eine zusätzliche IL gab, deren Zweck mich nicht angesprochen hat!foreach
Schleife ist, in welchem Fall für den speziellen Fall vonT
Als Wertetyp wird möglicherweise eine Box- / Unbox-Operation mithilfe der while-Schleife gespeichert. Dies wird jedoch nicht durch die IL bestätigt, die ich aus einer Version Ihrer Antwort mit erhalten habeforeach
. Ich denke jedoch immer noch, dass die bedingte Entsorgung des Iterators wichtig ist. Könnten Sie die Antwort so ändern, dass sie diese enthält?Ein paar Jahre später, aber dies verwendet Linq, gibt -1 zurück, wenn es nicht gefunden wird, erstellt keine zusätzlichen Objekte und sollte kurzschließen, wenn es gefunden wird [im Gegensatz zum Iterieren über die gesamte IEnumerable]:
Wo 'FirstOr' ist:
quelle
source.Where
undsource.DefaultIfEmpty
wird zum Beispiel jeweils ein erstellenIEnumerable
.Ich bin heute auf der Suche nach Antworten darüber gestolpert und dachte, ich würde meine Version zur Liste hinzufügen (kein Wortspiel beabsichtigt). Es verwendet den bedingten Nulloperator von c # 6.0
Ich habe einige "Rennen der alten Pferde" (Tests) durchgeführt und für große Sammlungen (~ 100.000) ist das schlimmste Szenario, das der gewünschte Gegenstand am Ende hat, 2x schneller als dies der Fall ist
ToList().FindIndex()
. Wenn sich der gewünschte Gegenstand in der Mitte befindet, ist er ~ 4x schneller.Für kleinere Sammlungen (~ 10.000) scheint es nur unwesentlich schneller zu sein
Hier ist, wie ich es getestet habe https://gist.github.com/insulind/16310945247fcf13ba186a45734f254e
quelle
Mit der Antwort von @Marc Gravell habe ich einen Weg gefunden, die folgende Methode zu verwenden:
um -1 zu erhalten, wenn der Gegenstand nicht gefunden werden kann:
Ich denke, dieser Weg könnte sowohl der schnellste als auch der einfachere sein. Allerdings habe ich die Leistungen noch nicht getestet.
quelle
Eine Alternative zum nachträglichen Suchen des Index besteht darin, die Aufzählung zu umbrechen, ähnlich wie bei der Verwendung der Linq GroupBy () -Methode.
Welches gibt einen Anwendungsfall von:
quelle
Dies kann mit einer Erweiterung (die als Proxy fungiert) sehr cool werden, zum Beispiel:
Dadurch werden der Sammlung, auf die über diese
Index
Eigenschaft zugegriffen werden kann, automatisch Indizes zugewiesen .Schnittstelle:
Benutzerdefinierte Erweiterung (wahrscheinlich am nützlichsten für die Arbeit mit EF und DbContext):
quelle