Vra

Is daar 'n beter manier om dit te doen?

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.w.z. Ek is op soek na 'n meer doeltreffende of meer elegante manier om die posisies van die voorwerpe wat ooreenstem met die kriteria te kry.

Was dit nuttig?

Oplossing

Jy kan maklik jou eie uitbreiding metode:

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

gebruik dit dan met:

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

Ander wenke

As jy net die gebruik van die voorbeeld as 'n manier om te leer LINQ, ignoreer hierdie post.


Dit is nie vir my duidelik dat LINQ is eintlik die beste manier om dit te doen. onder die kode lyk asof dit meer doeltreffend sou wees, aangesien geen nuwe anonieme tipe moet geskep word. Verleen, kan jou voorbeeld word slinks en die tegniek kan meer nuttig in 'n ander konteks, byvoorbeeld in 'n datastruktuur waar dit voordeel kan trek uit 'n indeks op waarde, maar die kode hieronder is redelik reguit vorentoe, verstaanbaar (geen gedagte vereis) en waarskynlik meer doeltreffend te maak.

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

Lyk goed vir my. Jy kan 'n paar karakters te red deur die verandering van die Gekose om:

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

Daar is ook FindIndex metode in Versameling Lys waarvoor jy 'n delete metode wat die indeks kan terugkeer uit die versameling te skep. jy kan verwys na die volgende skakel in MSDN http://msdn.microsoft.com /en-us/library/x1xzf2ca.aspx .

Hoe gaan dit? Dit is soortgelyk aan die oorspronklike plakkaat se maar ek kies eers die indekse en dan bou 'n versameling wat ooreenstem met die kriteria.

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

Dit is 'n bietjie minder doeltreffend as 'n paar van die ander antwoorde as die lys ten volle twee keer word herhaal oor.

Ek bespreek hierdie interessante probleem met 'n kollega en eers het ek gedink JonSkeet se oplossing was groot, maar my kollega het daarop gewys een probleem, naamlik dat indien die funksie is 'n uitbreiding van IEnumerable<T>, dan is dit kan gebruik word waar 'n versameling implemente dit .

Met 'n skikking, dit is veilig om te sê dat die bevel wat met foreach sal gerespekteer word (dit wil sê foreach sal Itereer van begin tot die einde), maar dit sal nie noodwendig die geval met ander versamelings (Lys, woordeboek, ens), waar te wees foreach sal weerspieël nie noodwendig "orde van inskrywing". Tog is die funksie is daar, en dit kan misleidend wees.

In die einde, ek beland met iets soortgelyk aan antwoord tvanfosson, maar as 'n uitbreiding metode, vir skikkings:

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();
}

Kom ons hoop dat List.ToArray sal die einde respek vir die laaste operasie ...

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top