Saya memiliki angka dari minus 1000 hingga plus 1000 dan saya memiliki array dengan angka di dalamnya. Seperti ini:
[2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
Saya ingin nomor yang saya punya berubah menjadi nomor array terdekat.
Misalnya saya mendapatkan 80
nomor yang saya inginkan 82
.
javascript
arrays
cupu
sumber
sumber
x
, melalui array satu per satu, dibandingkani
dengan angka saat ini dalam array, jika perbedaan antara itu dani
lebih kecil dari nilai saat ini dix
, setelx
ke nomor array saat ini. Setelah selesai,x
miliki nomor terdekati
dari array.Jawaban:
Versi ES5:
sumber
goal
untuk mengurangi, Anda harus merujuknya dari lingkup global.Inilah pseudo-code yang harus dapat dikonversi menjadi bahasa prosedural apa pun:
Itu hanya berhasil membedakan mutlak antara jumlah yang diberikan dan setiap elemen array dan memberi Anda kembali salah satu yang dengan perbedaan minimal.
Untuk nilai contoh:
Sebagai bukti konsep, inilah kode Python yang saya gunakan untuk menunjukkan ini dalam tindakan:
Dan jika kau benar - benar membutuhkannya dalam Javascript, lihat di bawah untuk file HTML lengkap yang menunjukkan fungsi dalam aksi:
Sekarang ingatlah bahwa mungkin ada ruang untuk peningkatan efisiensi jika, misalnya, item data Anda diurutkan (yang dapat disimpulkan dari data sampel tetapi Anda tidak secara eksplisit menyatakannya). Anda bisa, misalnya, menggunakan pencarian biner untuk menemukan item terdekat.
Anda juga harus mengingatnya, kecuali Anda harus melakukannya berkali- kali per detik, peningkatan efisiensi sebagian besar tidak akan terlihat kecuali set data Anda menjadi jauh lebih besar.
Jika kamu tidak ingin mencoba cara itu (dan dapat menjamin array diurutkan dalam urutan menaik), ini adalah baik titik awal:
Ini pada dasarnya menggunakan tanda kurung dan memeriksa nilai tengah untuk mengurangi ruang solusi hingga setengahnya untuk setiap iterasi, sebuah
O(log N)
algoritma klasik sedangkan pencarian berurutan di atas adalahO(N)
:Seperti yang dinyatakan, itu seharusnya tidak membuat banyak perbedaan untuk dataset kecil atau untuk hal-hal yang tidak perlu terlalu cepat, tetapi ini adalah opsi yang mungkin ingin Anda pertimbangkan.
sumber
Versi ES6 (2015):
Untuk dapat digunakan kembali, Anda dapat membungkus fungsi kari yang mendukung tempat penampung ( http://ramdajs.com/0.19.1/docs/#curry atau https://lodash.com/docs#curry ). Ini memberikan banyak fleksibilitas tergantung pada apa yang Anda butuhkan:
sumber
Kode kerja seperti di bawah ini:
sumber
Bekerja dengan array yang tidak disortir
Meskipun ada beberapa solusi bagus yang diposting di sini, JavaScript adalah bahasa yang fleksibel yang memberi kami alat untuk menyelesaikan masalah dengan berbagai cara. Itu semua bermuara pada gaya Anda, tentu saja. Jika kode Anda lebih fungsional, Anda akan menemukan pengurangan variasi yang cocok, yaitu:
Namun, beberapa orang mungkin kesulitan membaca, tergantung pada gaya pengkodeannya. Karena itu saya mengusulkan cara baru untuk menyelesaikan masalah:
Bertentangan dengan pendekatan lain yang menemukan nilai minimum menggunakan
Math.min.apply
, ini tidak memerlukan array inputarr
untuk diurutkan . Kami tidak perlu peduli dengan indeks atau mengurutkannya sebelumnya.Saya akan menjelaskan kode baris demi baris untuk kejelasan:
arr.map(function(k) { return Math.abs(k - x) })
Menciptakan array baru, pada dasarnya menyimpan nilai absolut dari angka yang diberikan (angka masukarr
) dikurangi angka input (x
). Kami akan mencari nomor terkecil berikutnya (yang juga paling dekat dengan nomor input)Math.min.apply(Math, indexArr)
Ini adalah cara yang sah untuk menemukan angka terkecil dalam array yang baru saja kita buat sebelumnya (tidak lebih dari itu)arr[indexArr.indexOf(min)]
Ini mungkin bagian yang paling menarik. Kami telah menemukan angka terkecil kami, tetapi kami tidak yakin apakah kami harus menambah atau mengurangi angka awal (x
). Itu karena kami duluMath.abs()
menemukan perbedaannya. Namun,array.map
membuat (secara logis) peta larik input, menjaga indeks di tempat yang sama. Oleh karena itu, untuk mengetahui nomor terdekat kami hanya mengembalikan indeks minimum yang ditemukan dalam array yang diberikanindexArr.indexOf(min)
.Saya telah membuat nampan yang menunjukkannya.
sumber
3n
dan ES5 meskipun Anda menjawab pada tahun 2016 dan solusi lain baik-baik saja meskipun noob ini yang mengajukan pertanyaan ini jelas bukan programmer pada saat itu.O(n)
solusi Anda berkinerja sekitar 100k ops / dtk kurang dari @paxdiabloO(log n)
pada angka acak. Saat mendesain suatu algoritma selalu mengurutkan terlebih dahulu yang mereka katakan. (Kecuali jika Anda tahu apa yang Anda lakukan dan Anda memiliki tolok ukur untuk mendukung Anda.)const findClosest = goal => (a,b) => Math.abs(a - goal) < Math.abs(b - goal) ? a : b;
[2, 42, 82, 122, 162, 202, 242, 282, 322, 362].reduce(findClosest(80))
Untuk array yang diurutkan (pencarian linear)
Semua jawaban sejauh ini berkonsentrasi pada pencarian melalui seluruh array. Mengingat array Anda sudah diurutkan dan Anda benar-benar hanya ingin nomor terdekat ini mungkin solusi tercepat:
Perhatikan bahwa algoritme dapat sangat ditingkatkan misalnya menggunakan pohon biner.
sumber
a[i]
ataui[0]
.Semua solusi over-engineered.
Sesederhana:
sumber
Solusi ini menggunakan ES5 quantential quantifier
Array#some
, yang memungkinkan untuk menghentikan iterasi, jika suatu kondisi terpenuhi.Sebaliknya
Array#reduce
, itu tidak perlu mengulangi semua elemen untuk satu hasil.Di dalam callback, absolut
delta
antara nilai yang dicari dan aktualitem
diambil dan dibandingkan dengan delta terakhir. Jika lebih besar atau sama, iterasi berhenti, karena semua nilai lain dengan delta mereka lebih besar dari nilai sebenarnya.Jika
delta
dalam panggilan balik lebih kecil, maka item yang sebenarnya ditetapkan untuk hasilnya dandelta
disimpan dalamlastDelta
.Akhirnya, nilai yang lebih kecil dengan delta yang sama diambil, seperti dalam contoh di bawah ini
22
, yang menghasilkan2
.Jika ada prioritas nilai yang lebih besar, cek delta harus diubah dari:
untuk:
Ini akan sesuai dengan
22
, hasilnya42
(Prioritas nilai yang lebih besar).Fungsi ini membutuhkan nilai yang diurutkan dalam array.
Kode dengan prioritas nilai yang lebih kecil:
Kode dengan prioritas nilai yang lebih besar:
sumber
closestValue([ 2, 2, 42, 80 ], 50) === 2
ES6
Bekerja dengan array yang diurutkan dan tidak disortir
Bilangan Integer dan Mengapung, String disambut
Contoh:
sumber
Saya tidak tahu apakah saya seharusnya menjawab pertanyaan lama, tetapi karena posting ini muncul pertama kali di pencarian Google, saya berharap Anda akan memaafkan saya menambahkan solusi saya & 2c saya di sini.
Menjadi malas, saya tidak percaya bahwa solusi untuk pertanyaan ini adalah LOOP, jadi saya mencari lebih banyak dan kembali dengan fungsi filter :
Itu saja !
sumber
goog.math.clamp
(penutupan google) hanya dengan array dan tanpa peduli dengan batas bawah.Jawaban saya untuk pertanyaan serupa adalah akuntansi untuk ikatan juga dan itu dalam Javascript biasa, meskipun tidak menggunakan pencarian biner sehingga itu adalah O (N) dan bukan O (logN):
https://stackoverflow.com/a/26429528/986160
sumber
Saya suka pendekatan dari Fusion, tetapi ada kesalahan kecil di dalamnya. Seperti itu benar:
Itu juga sedikit lebih cepat karena menggunakan
for
loop yang ditingkatkan .Pada akhirnya saya menulis fungsi saya seperti ini:
Saya mengujinya
console.time()
dan sedikit lebih cepat daripada fungsi lainnya.sumber
improved for loop
? Loop terbalik tidak selalu merupakan peningkatan kinerja..length
hanya sekali, ketika Anda menyatakani
, sedangkan untuk loop ini. Tapi saya pikirvar i = arr.length;while (i--) {}
akan lebih cepatwhile
. Sekarang bahkan lebih cepat.Pencarian biner yang sedikit dimodifikasi pada array akan bekerja.
sumber
Untuk rentang kecil, hal yang paling sederhana adalah memiliki larik peta, di mana, misalnya entri ke-80 akan memiliki nilai 82 di dalamnya, untuk menggunakan contoh Anda. Untuk rentang yang jauh lebih besar, jarang, mungkin cara untuk pergi adalah pencarian biner.
Dengan bahasa kueri, Anda dapat meminta nilai agak jauh di kedua sisi nomor input Anda dan kemudian menyortir daftar yang berkurang. Tetapi SQL tidak memiliki konsep "berikutnya" atau "sebelumnya" yang baik, untuk memberi Anda solusi "bersih".
sumber
Varian lain di sini kami memiliki jangkauan melingkar yang menghubungkan kepala dan kaki dan hanya menerima nilai minimum untuk input yang diberikan. Ini membantu saya mendapatkan nilai kode char untuk salah satu algoritma enkripsi.
sumber
sumber
Yang paling efisien adalah pencarian biner. Namun bahkan solusi sederhana dapat keluar ketika nomor berikutnya adalah pertandingan lebih lanjut dari saat ini . Hampir semua solusi di sini tidak memperhitungkan array yang dipesan dan mengulangi semuanya: /
Ini dapat dijalankan pada non-primitif juga misalnya
closest(data, 21, item => item.age)
Ubah
find
kefindIndex
untuk mengembalikan indeks dalam array.sumber
Untuk Menemukan Dua Nomor Terdekat dalam array
sumber
Berikut ini cuplikan kode untuk menemukan elemen terdekat ke nomor dari array di Complexity O (nlog (n)): -
Input: - {1,60,0, -10,100,87,56} Elemen: - 56 Nomor Terdekat dalam Array: - 60
Kode Sumber (Jawa):
sumber