Temukan indeks nilai dalam sebuah array

113

Dapatkah LINQ digunakan untuk menemukan indeks nilai dalam array?

Misalnya, loop ini menempatkan indeks kunci dalam sebuah array.

for (int i = 0; i < words.Length; i++)
{
    if (words[i].IsKey)
    {
        keyIndex = i;
    }
}
initialZero
sumber
Sebenarnya, hanya mendapatkan kata-katanya juga tidak masalah.
initialZero

Jawaban:

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

Itu benar-benar memberi Anda indeks integer dan bukan objeknya, terlepas dari kelas khusus apa yang telah Anda buat

sidney.andrews
sumber
1
Mengapa ini tidak dijadikan metode ekstensi System.Linqsecara default? Di situlah segalanya seperti ini!
qJake
63

Untuk array, Anda dapat menggunakan Array.FindIndex<T>:

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

Untuk daftar, Anda dapat menggunakan List<T>.FindIndex:

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

Anda juga dapat menulis metode ekstensi umum yang berfungsi untuk 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;
}

Dan Anda juga dapat menggunakan LINQ:

int keyIndex = words
    .Select((v, i) => new {Word = v, Index = i})
    .FirstOrDefault(x => x.Word.IsKey)?.Index ?? -1;
Paolo Moretti
sumber
2
Ada juga Daftar (T) .FindIndex metode
tdc
@Paolo bagaimana dengan Daftar yang dihasilkan dari Lambda? Saya mendapatkan kesalahan predikat.
Mihir Patel
10
int keyIndex = words.TakeWhile(w => !w.IsKey).Count();
Jonas Bötel
sumber
3
+1 tetapi, bagaimana jika item tidak ada? kita akan mendapatkan 0, tetapi indeksnya -1
Arsen Mkrtchyan
@ArsenMkrtchyan Jika item tidak ada, ini menghasilkan kata
Jim Balter
@ArsenMkrtchyan Anda menulis "kami akan mendapatkan 0" ... itu salah. Anda menulis "tetapi indeksnya -1" ... itu juga salah. -1 adalah indikator kegagalan yang umum, tetapi itu bukan satu-satunya yang mungkin. Nilai apa pun yang tidak berada dalam 0..words.Length-1 akan dilakukan.
Jim Balter
1
@JimBalter, maksud saya jika item tidak ada ekspresi akan mengembalikan 0, apa yang salah di dalamnya? Saya setuju bahwa -1 adalah indikator umum, tetapi setuju bahwa 99% kasus -1 adalah nilai yang diharapkan jika item tidak ada. setidaknya 0 salah ketika item tidak ada
Arsen Mkrtchyan
7

Jika Anda ingin mencari kata yang bisa Anda gunakan

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

Ini memberi Anda item pertama yang IsKey benar (jika mungkin ada non, Anda mungkin ingin menggunakan .FirstOrDefault()

Untuk mendapatkan item dan indeks, Anda dapat menggunakan

KeyValuePair<WordType, int> word = words.Select((item, index) => new KeyValuePair<WordType, int>(item, index)).Where(item => item.Key.IsKey).First();
Grizzly
sumber
Linq itu gila. Saya pikir obat generik Java gila. Bagaimanapun, terima kasih atas semua bantuannya.
initialZero
Apakah mentransmisikan nilai kembali merupakan praktik yang diterima atau adakah cara untuk menentukan jenis kata?
initialZero
ok, saya datang dengan ini. DecodedMessageWord keyWord = words.Where (x => x.IsKey == true). Pertama <DecodedMessageWord> ();
initialZero
5
@initialZero periksa kelebihannya karena First, dibutuhkan predikat, Anda tidak perlu ekstensi Where.
Yuriy Faktorovich
3

Coba ini...

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

sumber
2
Ini sepertinya solusi yang sangat lemah dibandingkan dengan jawaban Grizzly dan masenkablast. masenkablast menjawab pertanyaan asli dan Grizzly memberikan solusi yang lebih baik untuk menemukan kata tersebut, karena "var" terakhirnya adalah kata sebenarnya dan bukan <TSource> yang tidak terhitung banyaknya yang berisi 1 kata.
Yakobus
2

Baru saja memposting penerapan metode ekstensi IndexWhere () saya (dengan pengujian unit):

http://snipplr.com/view/53625/linq-index-of-item--indexwhere/

Contoh penggunaan:

int index = myList.IndexWhere(item => item.Something == someOtherThing);
joelsand
sumber
Saya tidak akan menggunakan perpustakaan itu, itu tidak menerapkan metode tersebut dengan benar. Ini mengabaikan pembuangan.
Yuriy Faktorovich
1

Solusi ini membantu saya lebih banyak, dari msdn microsoft :

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

queryadalah toList()pertanyaan Anda .

Roshna Omer
sumber
0
int index = -1;
index = words.Any (word => { index++; return word.IsKey; }) ? index : -1;
Marcel Valdez Orozco
sumber