Ini adalah cara yang paling populer (menurut saya) untuk memeriksa apakah suatu nilai ada dalam array:
for (int x : array)
{
if (x == value)
return true;
}
return false;
Namun, dalam sebuah buku yang saya baca bertahun-tahun yang lalu oleh, mungkin, Wirth atau Dijkstra, dikatakan bahwa gaya ini lebih baik (bila dibandingkan dengan loop sementara dengan jalan keluar di dalam):
int i = 0;
while (i < array.length && array[i] != value)
i++;
return i < array.length;
Dengan cara ini, kondisi keluar tambahan menjadi bagian eksplisit dari invarian loop, tidak ada kondisi tersembunyi dan keluar di dalam loop, semuanya lebih jelas dan lebih dalam cara pemrograman terstruktur. Saya biasanya lebih suka pola yang terakhir ini bila memungkinkan dan menggunakan for
-loop untuk hanya beralih dari a
ke b
.
Namun saya tidak dapat mengatakan bahwa versi pertama kurang jelas. Mungkin bahkan lebih jelas dan lebih mudah dipahami, setidaknya untuk pemula. Jadi saya masih bertanya pada diri sendiri pertanyaan mana yang lebih baik?
Mungkin seseorang dapat memberikan alasan yang bagus untuk mendukung salah satu metode?
Pembaruan: Ini bukan pertanyaan tentang beberapa titik pengembalian fungsi, lambdas atau menemukan elemen dalam array per se. Ini tentang bagaimana menulis loop dengan invarian yang lebih kompleks daripada ketidaksetaraan tunggal.
Pembaruan: OK, saya melihat inti dari orang-orang yang menjawab dan berkomentar: Saya mencampur-adukkan dalam loop foreach di sini, yang itu sendiri sudah jauh lebih jelas dan mudah dibaca daripada loop-sementara. Seharusnya aku tidak melakukan itu. Tapi ini juga pertanyaan yang menarik, jadi mari kita biarkan apa adanya: foreach-loop dan kondisi tambahan di dalam, atau loop-sementara dengan invarian loop eksplisit dan setelah kondisi setelah. Tampaknya foreach-loop dengan kondisi dan jalan keluar / istirahat menang. Saya akan membuat pertanyaan tambahan tanpa foreach-loop (untuk daftar tertaut).
sumber
collection.contains(foo)
Jawaban:
Saya pikir untuk loop sederhana, seperti ini, sintaks standar pertama jauh lebih jelas. Beberapa orang menganggap banyak pengembalian membingungkan atau bau kode, tetapi untuk sepotong kode sekecil ini, saya tidak percaya ini adalah masalah nyata.
Itu menjadi sedikit lebih bisa diperdebatkan untuk loop yang lebih kompleks. Jika konten loop tidak sesuai pada layar Anda dan memiliki beberapa pengembalian dalam loop, ada argumen yang harus dibuat bahwa beberapa titik keluar dapat membuat kode lebih sulit untuk dipelihara. Misalnya, jika Anda harus memastikan beberapa metode pemeliharaan negara berjalan sebelum keluar dari fungsi, akan mudah untuk tidak menambahkannya ke salah satu pernyataan pengembalian dan Anda akan menyebabkan bug. Jika semua kondisi akhir dapat diperiksa dalam loop sementara, Anda hanya memiliki satu titik keluar dan dapat menambahkan kode ini setelah itu.
Yang mengatakan, dengan loop terutama itu baik untuk mencoba dan menempatkan logika sebanyak mungkin ke dalam metode terpisah. Ini menghindari banyak kasus di mana metode kedua akan memiliki kelebihan. Lean loop dengan logika yang terpisah jelas akan lebih penting daripada gaya yang Anda gunakan. Juga, jika sebagian besar basis kode aplikasi Anda menggunakan satu gaya, Anda harus tetap dengan gaya itu.
sumber
Ini mudah.
Hampir tidak ada yang lebih penting daripada kejelasan bagi pembaca. Varian pertama yang saya temukan sangat sederhana dan jelas.
Versi 'membaik' kedua, saya harus membaca beberapa kali dan memastikan semua kondisi tepi benar.
Ada ZERO DOUBT yang merupakan gaya pengkodean yang lebih baik (yang pertama jauh lebih baik).
Sekarang - apa yang CLEAR bagi orang-orang dapat berbeda dari orang ke orang. Saya tidak yakin ada standar obyektif untuk itu (meskipun memposting ke forum seperti ini dan mendapatkan berbagai masukan orang dapat membantu).
Namun, dalam kasus khusus ini, saya dapat memberi tahu Anda mengapa algoritme pertama lebih jelas: Saya tahu seperti apa fungsi C ++ pada sintaksis wadah dan apa yang terlihat. Saya sudah menginternalisasi itu. Seseorang UNFAMILIAR (sintaks barunya) dengan sintaksis itu mungkin lebih suka variasi kedua.
Tapi begitu Anda tahu dan mengerti sintaks baru itu, itu konsep dasar yang bisa Anda gunakan. Dengan pendekatan loop iterasi (kedua), Anda harus hati-hati memeriksa bahwa pengguna dengan benar memeriksa semua kondisi tepi untuk mengulang seluruh array (misalnya kurang dari kurang dari atau sama dengan, indeks yang sama digunakan untuk pengujian dan untuk pengindeksan dll).
sumber
longerLength = true
, lalureturn longerLength
.length
. Jika itu benar-benar dinyatakan sebagai array dan bukan pointer, mereka dapat menggunakansizeof
, atau jika itu adalahstd::array
, fungsi anggota yang benar adalahsize()
, tidak adalength
properti.sizeof
akan dalam byte ... Yang paling umum sejak C ++ 17 adalahstd::size()
.Tidak terlalu. Variabel
i
ada di luar loop sementara di sini dan dengan demikian bagian dari lingkup luar, sementara (pun intended)x
darifor
-loop hanya ada dalam lingkup loop. Lingkup adalah salah satu cara yang sangat penting untuk memperkenalkan struktur pada pemrograman.sumber
Kedua loop memiliki semantik yang berbeda:
Loop pertama hanya menjawab pertanyaan ya / tidak sederhana: "Apakah array berisi objek yang saya cari?" Itu dilakukan dengan cara yang sesingkat mungkin.
Loop kedua menjawab pertanyaan: "Jika array berisi objek yang saya cari, apa indeks dari kecocokan pertama?" Sekali lagi, ia melakukannya dengan cara sesingkat mungkin.
Karena jawaban untuk pertanyaan kedua benar-benar memberikan lebih banyak informasi daripada jawaban untuk pertanyaan pertama, Anda dapat memilih untuk menjawab pertanyaan kedua dan kemudian mendapatkan jawaban dari pertanyaan pertama. Itulah yang dilakukan garis
return i < array.length;
itu.Saya percaya bahwa biasanya yang terbaik adalah hanya menggunakan alat yang sesuai dengan tujuan kecuali Anda dapat menggunakan kembali alat yang sudah ada dan lebih fleksibel. Yaitu:
bool
variabel dan istirahat juga baik-baik saja. (Menghindarireturn
pernyataan kedua , jawaban tersedia dalam variabel alih-alih fungsi).std::find
baik-baik saja (penggunaan kembali kode!).bool
tidak.sumber
Saya akan menyarankan opsi ketiga sama sekali:
Ada banyak alasan berbeda untuk beralih pada array: Periksa apakah ada nilai tertentu, ubah array menjadi array lain, hitung nilai agregat, filter beberapa nilai dari array ... Jika Anda menggunakan dataran untuk loop, tidak jelas sekilas secara khusus bagaimana for loop digunakan. Namun, sebagian besar bahasa modern memiliki API kaya pada struktur data lariknya yang membuat maksud yang berbeda ini sangat eksplisit.
Bandingkan mengubah satu array menjadi yang lain dengan for loop:
dan menggunakan
map
fungsi gaya JavaScript :Atau menjumlahkan array:
melawan:
Berapa lama Anda mengerti apa ini?
melawan
Dalam ketiga kasus tersebut, sementara for loop jelas dapat dibaca, Anda harus meluangkan waktu untuk mencari tahu bagaimana for loop digunakan dan memeriksa apakah semua penghitung dan kondisi keluar sudah benar. Fungsi gaya lambda modern membuat tujuan loop sangat eksplisit, dan Anda tahu pasti bahwa fungsi API yang dipanggil diimplementasikan dengan benar.
Sebagian besar bahasa modern, termasuk JavaScript , Ruby , C # , dan Java , menggunakan gaya interaksi fungsional ini dengan array dan koleksi serupa.
Secara umum, sementara saya tidak berpikir menggunakan untuk loop selalu salah, dan ini adalah masalah selera pribadi, saya telah menemukan diri saya sangat menyukai menggunakan gaya ini bekerja dengan array. Ini secara khusus karena meningkatnya kejelasan dalam menentukan apa yang dilakukan setiap loop. Jika bahasa Anda memiliki fitur atau alat serupa di perpustakaan standarnya, saya sarankan Anda mempertimbangkan untuk mengadopsi gaya ini juga!
sumber
array.find
memunculkan pertanyaan, karena kita kemudian harus membahas cara terbaik untuk menerapkanarray.find
. Kecuali jika Anda menggunakan perangkat keras denganfind
operasi bawaan, kami harus menulis loop di sana.find
di perpustakaan standar mereka. Tidak diragukan lagi, perpustakaan ini mengimplementasikanfind
dan kerabatnya menggunakan untuk loop, tapi itulah fungsi yang baik: itu mengabstraksi rincian teknis dari konsumen fungsi, yang memungkinkan programmer untuk tidak perlu memikirkan rincian itu. Jadi meskipunfind
kemungkinan diimplementasikan dengan for loop, tetap membantu membuat kode lebih mudah dibaca, dan karena sering di perpustakaan standar, menggunakannya tidak menambah overhead atau risiko yang berarti.Semuanya bermuara pada apa yang dimaksud dengan 'lebih baik'. Untuk programmer praktis, umumnya berarti efisien - yaitu dalam hal ini, keluar langsung dari loop menghindari satu perbandingan ekstra, dan mengembalikan konstanta Boolean menghindari perbandingan duplikat; ini menghemat siklus. Dijkstra lebih mementingkan pembuatan kode yang lebih mudah dibuktikan dengan benar . [Tampaknya bagi saya bahwa pendidikan CS di Eropa menganggap 'membuktikan kebenaran kode' jauh lebih serius daripada pendidikan CS di AS, di mana kekuatan ekonomi cenderung mendominasi praktik pengkodean]
sumber