Frage

Gibt es einen besseren Weg, dies zu tun?

string[] s = {"zero", "one", "two", "three", "four", "five"};

var x = 
s
.Select((a,i) => new {Value = a, Index = i})
.Where(b => b.Value.StartsWith("t"))
.Select(c => c.Index);

d. Ich bin für einen effizientere oder eleganten Weg, um die Positionen der Artikel aus, die Kriterien zu erhalten.

War es hilfreich?

Lösung

Sie können ganz einfach Ihre eigene Erweiterungsmethode hinzufügen:

public static IEnumerable<int> IndexesWhere<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
    int index=0;
    foreach (T element in source)
    {
        if (predicate(element))
        {
            yield return index;
        }
        index++;
    }
}

Dann verwenden Sie es mit:

string[] s = {"zero", "one", "two", "three", "four", "five"};
var x = s.IndexesWhere(t => t.StartsWith("t"));

Andere Tipps

Wenn Sie nur das Beispiel als eine Möglichkeit, mithilfe von LINQ zu lernen, ignorieren Sie diesen Beitrag.


Es ist mir nicht klar, dass LINQ tatsächlich der beste Weg, dies zu tun ist. Der Code scheint unten wie es effizienter wäre, da kein neuer anonymer Typ erstellt werden muss. Zugegeben, kann Ihr Beispiel ersonnen werden und die Technik könnte nützlicher in einem anderen Kontext, zum Beispiel in einer Datenstruktur, wo es von Vorteil, einen Index-Wert übernehmen könnte, aber der Code unten ist ziemlich geradlinig, verständlich (kein Gedanke erforderlich) und wohl auch effizienter.

string[] s = {"zero", "one", "two", "three", "four", "five"};
List<int> matchingIndices = new List<int>();

for (int i = 0; i < s.Length; ++i) 
{
   if (s[i].StartWith("t"))
   {
      matchingIndices.Add(i);
   }
}

Es scheint mir in Ordnung. Sie könnten ein paar Zeichen speichern, indem Sie die Auswahl auf sich ändernde:

.Select((Value, Index) => new {Value, Index})

Es gibt auch Find Methode in Sammlungsliste, für die Sie eine Löschmethode erstellen, die den Index aus der Sammlung zurückkehren können. Sie können in Msdn auf dem folgenden Link finden Sie http://msdn.microsoft.com /en-us/library/x1xzf2ca.aspx .

Wie wäre es damit? Es ist ähnlich wie das ursprüngliche Plakat, aber ich zuerst die Indizes auswählen und dann eine Sammlung aufzubauen, die die Kriterien entsprechen.

var x = s.Select((a, i) => i).Where(i => s[i].StartsWith("t"));

Dies ist ein bisschen weniger effizient als einige der anderen Antworten, wie die Liste voll zweimal iteriert wird.

diskutierte ich dieses interessante Problem mit einem Kollegen und ich dachte zuerst JonSkeet Lösung war großartig, aber mein Kollege wies darauf hin, ein Problem, nämlich dass, wenn die Funktion eine Erweiterung ist, IEnumerable<T> dann kann es verwendet werden, wo eine Sammlung implementiert es .

Mit einer Reihe, dann ist es sicher der Auftrag mit foreach produziert sagen respektiert werden (dh foreach werde von dem ersten Iteration zu halten), aber es wäre der Fall mit anderen Sammlungen (List, Wörterbuch, usw.) nicht unbedingt sein, wo foreach nicht reflektiert unbedingt "Reihenfolge der Eingabe". Doch die Funktion ist da, und es kann irreführend sein.

Am Ende landete ich mit etwas ähnlich der, tvanfosson Antwort, sondern als Erweiterung Methode für Arrays:

public static int[] GetIndexes<T>(this T[]source, Func<T, bool> predicate)
{
    List<int> matchingIndexes = new List<int>();

    for (int i = 0; i < source.Length; ++i) 
    {
        if (predicate(source[i]))
        {
            matchingIndexes.Add(i);
        }
    }
    return matchingIndexes.ToArray();
}

Hier hofft List.ToArray den Auftrag für die letzte Operation respektieren ...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top