Trova l'indice di un valore in un array


113

Linq può essere usato in qualche modo per trovare l'indice di un valore in un array?

Ad esempio, questo ciclo individua l'indice della chiave all'interno di un array.

for (int i = 0; i < words.Length; i++)
{
    if (words[i].IsKey)
    {
        keyIndex = i;
    }
}

In realtà, anche solo ricevere la parola andrebbe bene.
initialZero

Risposte:


183
int keyIndex = Array.FindIndex(words, w => w.IsKey);

In questo modo ottieni l'indice intero e non l'oggetto, indipendentemente dalla classe personalizzata che hai creato


1
Perché questo non è stato trasformato in un metodo di estensione System.Linqper impostazione predefinita? È lì che sta tutto il resto!
qJake

63

Per gli array puoi usare Array.FindIndex<T>::

int keyIndex = Array.FindIndex(words, w => w.IsKey);

Per gli elenchi puoi utilizzare List<T>.FindIndex:

int keyIndex = words.FindIndex(w => w.IsKey);

Puoi anche scrivere un metodo di estensione generico che funzioni per qualsiasi Enumerable<T>:

///<summary>Finds the index of the first item matching an expression in an enumerable.</summary>
///<param name="items">The enumerable to search.</param>
///<param name="predicate">The expression to test the items against.</param>
///<returns>The index of the first matching item, or -1 if no items match.</returns>
public static int FindIndex<T>(this IEnumerable<T> items, Func<T, bool> predicate) {
    if (items == null) throw new ArgumentNullException("items");
    if (predicate == null) throw new ArgumentNullException("predicate");

    int retVal = 0;
    foreach (var item in items) {
        if (predicate(item)) return retVal;
        retVal++;
    }
    return -1;
}

E puoi usare anche LINQ:

int keyIndex = words
    .Select((v, i) => new {Word = v, Index = i})
    .FirstOrDefault(x => x.Word.IsKey)?.Index ?? -1;

2
C'è anche un metodo List (T) .FindIndex
tdc

@Paolo che ne dici di una lista generata da Lambda? Ottengo l'errore del predicato.
Mihir Patel

10
int keyIndex = words.TakeWhile(w => !w.IsKey).Count();

3
+1 ma, cosa succede se l'elemento non esiste? otterremo 0, ma l'indice è -1
Arsen Mkrtchyan

@ArsenMkrtchyan Se l'elemento non esiste, questo produce parole
Jim Balter,

@ArsenMkrtchyan Hai scritto "otterremo 0" ... era sbagliato. Hai scritto "ma l'indice è -1" ... anche questo è sbagliato. -1 è un comune indicatore di fallimento, ma non è l'unico possibile. Qualsiasi valore non compreso tra 0..words.Length-1 andrà bene.
Jim Balter

1
@ JimBalter, voglio dire se l'elemento non esiste l'espressione restituirà 0, cosa c'è di sbagliato in esso? Sono d'accordo sul fatto che -1 sia un indicatore comune, ma concordo sul fatto che è ovvio che il 99% dei casi -1 è il valore atteso quando l'elemento non esiste. almeno 0 è sbagliato quando l'oggetto non esiste
Arsen Mkrtchyan

7

Se vuoi trovare la parola puoi usare

var word = words.Where(item => item.IsKey).First();

Questo ti dà il primo elemento per il quale IsKey è vero (se potrebbe non esserci, potresti voler usare .FirstOrDefault()

Per ottenere sia l'oggetto che l'indice puoi usare

KeyValuePair<WordType, int> word = words.Select((item, index) => new KeyValuePair<WordType, int>(item, index)).Where(item => item.Key.IsKey).First();

linq è pazzo. Pensavo che i generici Java fossero pazzi. Comunque, grazie per tutto l'aiuto.
initialZero

Il casting del valore di ritorno è una pratica accettata o c'è un modo per definire il tipo di parola?
initialZero

ok, ho pensato a questo. DecodedMessageWord keyWord = words.Where (x => x.IsKey == true) .First <DecodedMessageWord> ();
initialZero

5
@initialZero controlla i sovraccarichi First, ci vuole un predicato, non hai bisogno di Where.
Yuriy Faktorovich

3

Prova questo...

var key = words.Where(x => x.IsKey == true);

2
Questa sembra una soluzione molto debole rispetto alle risposte di Grizzly e masenkablast. masenkablast risponde alla domanda originale e Grizzly fornisce una soluzione migliore per trovare la parola, poiché la sua "var" finale sarà la parola effettiva e non un IEnumerable <TSource> che contiene 1 parola.
James


1

Questa soluzione mi ha aiutato di più, da msdn microsoft :

var result =  query.AsEnumerable().Select((x, index) =>
              new { index,x.Id,x.FirstName});

queryè la tua toList()domanda.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.