Saya menulis ini:
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();
}
}
Tapi saya tidak tahu apakah itu sudah ada, bukan?
Max
pendekatan adalah bahwa: itu terus mencari, dan b: ia mengembalikan terakhir indeks ketika ada duplikat (orang biasanya memperkirakan indeks pertama)ToList()/FindIndex()
Melakukan trik terbaikJawaban:
Inti dari mengeluarkan segala sesuatu sebagai IEnumerable adalah agar Anda dapat dengan malas beralih pada isinya. Dengan demikian, tidak ada benar-benar sebuah konsep indeks. Apa yang Anda lakukan sebenarnya tidak masuk akal untuk IEnumerable. Jika Anda memerlukan sesuatu yang mendukung akses berdasarkan indeks, taruh dalam daftar atau koleksi aktual.
sumber
IEnumerable<>
. Saya tidak membeli keseluruhan dogma "Kamu harus melakukan ini".IEnumerable
makaEnumerable.ElementAt
tidak akan ada.IndexOf
hanyalah kebalikan - argumen apa pun yang menentangnya harus berlaku samaElementAt
.Saya akan mempertanyakan kebijaksanaan, tetapi mungkin:
(gunakan
EqualityComparer<T>.Default
untuk meniru!=
jika diperlukan) - tetapi Anda harus menonton untuk mengembalikan -1 jika tidak ditemukan ... jadi mungkin lakukan sajasumber
TakeWhile
itu pintar! Ingatlah ini kembaliCount
jika elemen tidak ada yang merupakan penyimpangan dari perilaku standar.Saya akan menerapkannya seperti ini:
sumber
==
mungkin perlu kerja?KVP<T, int?>
(nullable index)IList<T>
dan jika demikian, tunda metode IndexOf untuk berjaga-jaga jika ada optimasi tipe-spesifik.Cara saya saat ini melakukan ini sedikit lebih pendek dari yang sudah disarankan dan sejauh yang saya tahu memberikan hasil yang diinginkan:
Agak kikuk, tetapi berhasil dan cukup ringkas.
sumber
Cara terbaik untuk menangkap posisi adalah dengan
FindIndex
Fungsi ini hanya tersedia untukList<>
Contoh
Jika Anda memiliki enumerator atau array gunakan cara ini
atau
sumber
Saya pikir opsi terbaik adalah menerapkan seperti ini:
Itu juga tidak akan membuat objek anonim
sumber
Agak terlambat dalam permainan, saya tahu ... tapi inilah yang baru-baru ini saya lakukan. Ini sedikit berbeda dari milik Anda, tetapi memungkinkan pemrogram untuk menentukan apa yang harus operasi kesetaraan (predikat). Yang saya temukan sangat berguna ketika berhadapan dengan berbagai jenis, karena saya kemudian memiliki cara umum untuk melakukannya terlepas dari jenis objek dan
<T>
dibangun di operator kesetaraan.Ini juga memiliki jejak memori yang sangat sangat kecil, dan sangat, sangat cepat / efisien ... jika Anda peduli tentang itu.
Lebih buruk lagi, Anda hanya akan menambahkan ini ke daftar ekstensi Anda.
Ngomong-ngomong ... ini dia.
Semoga ini bisa membantu seseorang.
sumber
GetEnumerator
danMoveNext
bukan hanyaforeach
?foreach
akan memanggilDispose
enumerator jika mengimplementasikanIDisposable
. (Lihat stackoverflow.com/questions/4982396/… ) Karena kode dalam jawaban ini tidak tahu apakah hasil dari panggilanGetEnumerator
adalah atau tidak, harus dilakukan hal yang sama. Pada saat itu saya masih belum jelas bahwa ada manfaat perf, meskipun ada beberapa IL tambahan yang tujuannya tidak melompat ke arahku!foreach
loop, dalam hal ini untuk kasus tertentuT
menjadi tipe nilai mungkin menyimpan kotak / operasi unbox dengan menggunakan loop sementara. Namun, ini tidak didukung oleh IL yang saya dapatkan dari versi jawaban Andaforeach
. Saya masih berpikir pembuangan bersyarat iterator penting, meskipun. Bisakah Anda memodifikasi jawaban untuk memasukkan itu?Beberapa tahun kemudian, tetapi ini menggunakan Linq, mengembalikan -1 jika tidak ditemukan, tidak membuat objek tambahan, dan harus korsleting ketika ditemukan [sebagai lawan iterasi seluruh IEnumerable]:
Di mana 'FirstOr' adalah:
sumber
source.Where
dansource.DefaultIfEmpty
misalnya akan membuatIEnumerable
masing - masing.Tersandung di sini hari ini dalam mencari jawaban dan saya pikir saya akan menambahkan versi saya ke daftar (No pun intended). Ini menggunakan operator bersyarat nol dari c # 6.0
Saya telah melakukan beberapa 'balap kuda tua' (pengujian) dan untuk koleksi besar (~ 100.000), skenario terburuk item yang Anda inginkan adalah pada akhirnya, ini 2x lebih cepat daripada melakukannya
ToList().FindIndex()
. Jika Item yang Anda inginkan ada di tengah ~ 4x lebih cepat.Untuk koleksi yang lebih kecil (~ 10.000) sepertinya hanya sedikit lebih cepat
Inilah cara saya mengujinya https://gist.github.com/insulind/16310945247fcf13ba186a45734f254e
sumber
Menggunakan jawaban @Marc Gravell, saya menemukan cara untuk menggunakan metode berikut:
untuk mendapatkan -1 saat item tidak dapat ditemukan:
Saya kira cara ini bisa menjadi yang tercepat dan lebih sederhana. Namun, saya belum menguji kinerja.
sumber
Alternatif untuk menemukan indeks setelah faktanya adalah dengan membungkus Enumerable, agak mirip dengan menggunakan metode Linq GroupBy ().
Yang memberikan kasus penggunaan:
sumber
Ini bisa menjadi sangat keren dengan ekstensi (berfungsi sebagai proxy), misalnya:
Yang secara otomatis akan menetapkan indeks untuk koleksi yang dapat diakses melalui
Index
properti ini .Antarmuka:
Ekstensi khusus (mungkin paling berguna untuk bekerja dengan EF dan DbContext):
sumber