Ich habe eine Zahl von minus 1000 bis plus 1000 und ich habe ein Array mit Zahlen. So was:
[2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
Ich möchte, dass sich die Nummer, die ich habe, in die nächste Nummer des Arrays ändert.
Zum Beispiel bekomme 80
ich die Nummer, die ich bekommen möchte 82
.
javascript
arrays
Anfänger
quelle
quelle
x
, gehen Sie das Array nacheinander durch, vergleichen Sie siei
mit der aktuellen Nummer im Array, wenn die Differenz zwischen ihr undi
kleiner als der aktuelle Wert in istx
, setzen Sie siex
auf die aktuelle Array-Nummer. Wenn Sie fertig sind,x
haben Sie die Nummer,i
die dem Array am nächsten kommt .Antworten:
ES5-Version:
quelle
goal
Reduzierung nicht bestehen können , müssen Sie sie aus einem globalen Bereich referenzieren.Hier ist der Pseudocode, der in jede prozedurale Sprache konvertierbar sein sollte:
Es berechnet einfach die absoluten Unterschiede zwischen der angegebenen Anzahl und jedem Array-Element und gibt Ihnen einen der mit dem minimalen Unterschied zurück.
Für die Beispielwerte:
Als Proof of Concept ist hier der Python-Code, mit dem ich dies in Aktion gezeigt habe:
Und wenn Sie es wirklich in Javascript brauchen, finden Sie unten eine vollständige HTML-Datei, die die Funktion in Aktion demonstriert:
Denken Sie jetzt daran, dass möglicherweise die Effizienz verbessert werden kann, wenn beispielsweise Ihre Datenelemente sortiert sind (dies könnte aus den Beispieldaten abgeleitet werden, aber Sie geben es nicht explizit an). Sie können beispielsweise eine binäre Suche verwenden, um das nächstgelegene Element zu finden.
Sie sollten auch bedenken , dass, wenn Sie es tun müssen , viele Male pro Sekunde, werden die Effizienzverbesserungen werden meist unnoticable es sei denn , Ihre Datensätze bekommen viel größer.
Wenn Sie es auf diese Weise versuchen möchten (und garantieren können, dass das Array in aufsteigender Reihenfolge sortiert ist), ist dies ein guter Ausgangspunkt:
Grundsätzlich wird die Klammerung und Überprüfung des Mittelwerts verwendet, um den Lösungsraum für jede Iteration um die Hälfte zu reduzieren. Dies ist ein klassischer
O(log N)
Algorithmus, während die obige sequentielle Suche wie folgt lauteteO(N)
:Wie bereits erwähnt, das sollte nicht viel Unterschied für kleine Datenmengen oder für Dinge, die nicht brauchen blendend schnell zu sein, aber es ist eine Option , die Sie betrachten wünschen können.
quelle
ES6 (2015) Version:
Zur Wiederverwendbarkeit können Sie eine Curry-Funktion einbinden, die Platzhalter unterstützt ( http://ramdajs.com/0.19.1/docs/#curry oder https://lodash.com/docs#curry ). Dies bietet viel Flexibilität, je nachdem, was Sie benötigen:
quelle
Arbeitscode wie folgt:
quelle
Funktioniert mit unsortierten Arrays
Obwohl hier einige gute Lösungen veröffentlicht wurden, ist JavaScript eine flexible Sprache, mit der wir ein Problem auf viele verschiedene Arten lösen können. Natürlich hängt alles von Ihrem Stil ab. Wenn Ihr Code funktionaler ist, finden Sie die reduzierte Variation geeignet, dh:
Einige können dies jedoch je nach Codierungsstil schwer lesen. Deshalb schlage ich einen neuen Weg zur Lösung des Problems vor:
Im Gegensatz zu anderen Ansätzen mit
Math.min.apply
, muss das Eingabearrayarr
nicht sortiert werden . Wir müssen uns nicht um die Indizes kümmern oder sie vorher sortieren.Ich werde den Code der Klarheit halber Zeile für Zeile erklären:
arr.map(function(k) { return Math.abs(k - x) })
Erstellt ein neues Array, in dem im Wesentlichen die absoluten Werte der angegebenen Zahlen gespeichert werden (Zahl inarr
) abzüglich der eingegebenen Zahl (x
) . Wir werden als nächstes nach der kleinsten Zahl suchen (die auch der eingegebenen Zahl am nächsten kommt).Math.min.apply(Math, indexArr)
Dies ist ein legitimer Weg, um die kleinste Zahl in dem Array zu finden, das wir gerade zuvor erstellt haben (nichts weiter dazu)arr[indexArr.indexOf(min)]
Dies ist vielleicht der interessanteste Teil. Wir haben unsere kleinste Zahl gefunden, sind uns aber nicht sicher, ob wir die ursprüngliche Zahl addieren oder subtrahieren sollen (x
). Das liegt daran, dass wirMath.abs()
den Unterschied gefunden haben. Allerdingsarray.map
schafft (logisch) eine Karte der Eingangsanordnung, die Indizes an der gleichen Stelle zu halten. Um die nächstgelegene Zahl herauszufinden, geben wir einfach den Index des gefundenen Minimums im angegebenen Array zurückindexArr.indexOf(min)
.Ich habe einen Behälter erstellt, der dies demonstriert.
quelle
3n
und es ES5 ist, obwohl Sie 2016 antworten und andere Lösungen in Ordnung sind, obwohl dieser Noob, der diese Frage gestellt hat, zu diesem Zeitpunkt eindeutig kein Programmierer war.O(n)
abschneidet, aber ich habe die Zahlen für Sie angegeben und Ihre Lösung führtO(log n)
bei Zufallszahlen etwa 100.000 Ops / Sek. Weniger aus als @paxdiablo . Beim Entwerfen eines Algorithmus wird immer zuerst sortiert. (Außer wenn Sie wissen, was Sie tun und Benchmarks haben, die Sie unterstützen.)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))
Für sortierte Arrays (lineare Suche)
Alle bisherigen Antworten konzentrieren sich auf die Suche im gesamten Array. Wenn man bedenkt, dass Ihr Array bereits sortiert ist und Sie wirklich nur die nächste Nummer wollen, ist dies wahrscheinlich die schnellste Lösung:
Beachten Sie, dass der Algorithmus erheblich verbessert werden kann, z. B. mithilfe eines Binärbaums.
quelle
a[i]
oderi[0]
.Alle Lösungen sind überentwickelt.
Es ist so einfach wie:
quelle
Diese Lösung verwendet einen existenziellen ES5- Quantifizierer
Array#some
, mit dem die Iteration gestoppt werden kann, wenn eine Bedingung erfüllt ist.Im Gegensatz
Array#reduce
dazu müssen nicht alle Elemente für ein Ergebnis iteriert werden.Innerhalb des Rückrufs ein Absolut
delta
zwischen dem gesuchten Wert und dem tatsächlichen Wertitem
genommen und mit dem letzten Delta verglichen. Wenn größer oder gleich, stoppt die Iteration, da alle anderen Werte mit ihren Deltas größer als der tatsächliche Wert sind.Wenn der
delta
Rückruf kleiner ist, wird das eigentliche Element dem Ergebnis zugeordnet unddelta
in gespeichertlastDelta
.Schließlich werden kleinere Werte mit gleichen Deltas genommen, wie im folgenden Beispiel von
22
, was zu ergibt2
.Wenn es eine Priorität für größere Werte gibt, muss die Delta-Prüfung geändert werden von:
zu:
Dies würde mit
22
dem Ergebnis kommen42
einhergehen (Priorität größerer Werte).Diese Funktion benötigt sortierte Werte im Array.
Code mit Priorität kleinerer Werte:
Code mit Priorität größerer Werte:
quelle
closestValue([ 2, 2, 42, 80 ], 50) === 2
ES6
Funktioniert mit sortierten und unsortierten Arrays
Numbers Integers and Floats, Strings begrüßt
Beispiele:
quelle
Ich weiß nicht, ob ich eine alte Frage beantworten soll, aber da dieser Beitrag zuerst in der Google-Suche erscheint, hoffte ich, dass Sie mir verzeihen, dass ich meine Lösung und meine 2c hier hinzufüge.
Da ich faul war, konnte ich nicht glauben, dass die Lösung für diese Frage eine Schleife sein würde, also suchte ich ein bisschen mehr und kam mit der Filterfunktion zurück :
Das ist alles !
quelle
goog.math.clamp
(Google Closure) nur mit Arrays und ohne Rücksicht auf die Untergrenze.Meine Antwort auf eine ähnliche Frage berücksichtigt auch Bindungen und ist in einfachem Javascript, obwohl keine binäre Suche verwendet wird, also O (N) und nicht O (logN):
https://stackoverflow.com/a/26429528/986160
quelle
Ich mag den Ansatz von Fusion, aber es gibt einen kleinen Fehler. So ist es richtig:
Es ist auch etwas schneller, weil es die verbesserte
for
Schleife verwendet.Am Ende habe ich meine Funktion so geschrieben:
Ich habe es mit getestet
console.time()
und es ist etwas schneller als die andere Funktion.quelle
improved for loop
? Umgekehrte Schleifen sind nicht immer eine Leistungsverbesserung..length
nur einmal aus, wenn Sie deklariereni
, während für diese Schleife. Aber ich denkevar i = arr.length;while (i--) {}
wäre noch schnellerwhile
. Jetzt geht es noch schneller.Eine leicht modifizierte binäre Suche im Array würde funktionieren.
quelle
Für einen kleinen Bereich ist es am einfachsten, ein Kartenarray zu haben, in dem beispielsweise der 80. Eintrag den Wert 82 enthält, um Ihr Beispiel zu verwenden. Für einen viel größeren, spärlichen Bereich ist der Weg wahrscheinlich eine binäre Suche.
Mit einer Abfragesprache können Sie Werte in einiger Entfernung zu beiden Seiten Ihrer Eingabenummer abfragen und dann die resultierende reduzierte Liste sortieren. SQL hat jedoch kein gutes Konzept für "Weiter" oder "Zurück", um Ihnen eine "saubere" Lösung zu bieten.
quelle
Eine andere Variante hier ist ein kreisförmiger Bereich, der Kopf bis Fuß verbindet und nur einen minimalen Wert für die gegebene Eingabe akzeptiert. Dies hatte mir geholfen, Zeichencodewerte für einen der Verschlüsselungsalgorithmen zu erhalten.
quelle
quelle
Am effizientesten wäre eine binäre Suche. Es können jedoch auch einfache Lösungen beendet werden, wenn die nächste Zahl weiter mit der aktuellen übereinstimmt . Fast alle Lösungen hier berücksichtigen nicht, dass das Array geordnet ist und durch das Ganze iteriert: /
Dies kann auch auf Nicht-Grundelementen ausgeführt werden, z
closest(data, 21, item => item.age)
Wechseln Sie
find
zufindIndex
, um den Index im Array zurückzugeben.quelle
So finden Sie zwei nächstgelegene Zahlen im Array
quelle
Hier ist das Code-Snippet, um das Element zu finden, das einer Zahl aus einem Array in Complexity O (nlog (n)) am nächsten kommt: -
Eingabe: - {1,60,0, -10,100,87,56} Element: - 56 Nächste Zahl im Array: - 60
Quellcode (Java):
quelle