Mam liczbę od minus 1000 do plus 1000 i mam tablicę z liczbami. Lubię to:
[2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
Chcę, aby liczba, którą otrzymałem, zmieniła się na najbliższą liczbę w tablicy.
Na przykład otrzymuję 80
numer, który chcę, aby otrzymał 82
.
javascript
arrays
Nowicjusz
źródło
źródło
x
, przejrzyj tablicę jeden po drugim, porównaji
z bieżącą liczbą w tablicy, jeśli różnica między nią ai
jest mniejsza niż aktualna wartość wx
, ustawx
aktualny numer tablicy. Po zakończeniux
ma numer najbliższyi
tablicy.Odpowiedzi:
Wersja ES5:
źródło
goal
do redukcji, musisz odwołać się do niego z zakresu globalnego.Oto pseudokod, który można zamienić na dowolny język proceduralny:
Po prostu oblicza bezwzględne różnice między podaną liczbą i każdym elementem tablicy i zwraca jedną z tych z minimalną różnicą.
Przykładowe wartości:
Jako dowód koncepcji, oto kod Pythona, którego użyłem do pokazania tego w akcji:
A jeśli naprawdę potrzebujesz tego w JavaScript, zobacz poniżej pełny plik HTML, który demonstruje tę funkcję w akcji:
Teraz należy pamiętać, że może istnieć pole do poprawy wydajności, jeśli na przykład elementy danych są posortowane (co można wywnioskować z przykładowych danych, ale nie podasz tego jawnie). Możesz na przykład użyć wyszukiwania binarnego, aby znaleźć najbliższy element.
Należy również pamiętać, że jeśli nie musisz robić tego wiele razy na sekundę, poprawa wydajności będzie w większości niezauważalna, chyba że zbiory danych staną się znacznie większe.
Jeśli nie chcesz, aby spróbować go w ten sposób (i może zagwarantować, tablica jest posortowana w kolejności rosnącej), jest to dobry punkt wyjścia:
Zasadniczo używa nawiasów i sprawdzania wartości środkowej, aby zmniejszyć przestrzeń rozwiązania o połowę dla każdej iteracji, klasyczny
O(log N)
algorytm, podczas gdy powyższe wyszukiwanie sekwencyjne wyglądało następującoO(N)
:Jak wspomniano, nie powinno to mieć większego znaczenia w przypadku małych zestawów danych lub rzeczy, które nie muszą być oślepiająco szybkie, ale jest to opcja, którą warto rozważyć.
źródło
Wersja ES6 (2015):
W celu ponownego wykorzystania możesz zawinąć funkcję curry, która obsługuje symbole zastępcze ( http://ramdajs.com/0.19.1/docs/#curry lub https://lodash.com/docs#curry ). Daje to dużą elastyczność w zależności od potrzeb:
źródło
Kod roboczy, jak poniżej:
źródło
Działa z niesortowanymi tablicami
Chociaż zamieszczono tutaj kilka dobrych rozwiązań, JavaScript jest elastycznym językiem, który daje nam narzędzia do rozwiązywania problemów na wiele różnych sposobów. Oczywiście wszystko zależy od Twojego stylu. Jeśli Twój kod jest bardziej funkcjonalny, wariant redukcji będzie odpowiedni, np .:
Jednak niektórym może się to wydawać trudne do odczytania, w zależności od stylu kodowania. Dlatego proponuję nowy sposób rozwiązania problemu:
W przeciwieństwie do innych podejść do znajdowania wartości minimalnej przy użyciu
Math.min.apply
, ta metoda nie wymagaarr
sortowania tablicy wejściowej . Nie musimy przejmować się indeksami ani ich wcześniej sortować.Dla jasności wyjaśnię kod wiersz po wierszu:
arr.map(function(k) { return Math.abs(k - x) })
Tworzy nową tablicę, zasadniczo przechowującą wartości bezwzględne podanych liczb (liczba warr
) minus liczba wejściowa (x
). Następnie poszukamy najmniejszej liczby (która jest również najbliższa liczbie wejściowej)Math.min.apply(Math, indexArr)
To jest legalny sposób na znalezienie najmniejszej liczby w tablicy, którą właśnie utworzyliśmy (nic więcej)arr[indexArr.indexOf(min)]
To chyba najbardziej interesująca część. Znaleźliśmy naszą najmniejszą liczbę, ale nie jesteśmy pewni, czy powinniśmy dodać, czy odjąć liczbę początkową (x
). To dlatego, że kiedyśMath.abs()
znajdowaliśmy różnicę. Jednakarray.map
tworzy (logicznie) mapę tablicy wejściowej, zachowując indeksy w tym samym miejscu. Dlatego, aby znaleźć najbliższą liczbę, po prostu zwracamy indeks znalezionego minimum w podanej tablicyindexArr.indexOf(min)
.Stworzyłem kosz demonstrujący to.
źródło
3n
ES5, mimo że odpowiadasz w 2016 roku, a inne rozwiązania są w porządku, mimo że ten noob, który zadał to pytanie, najwyraźniej nie był wówczas programistą.O(n)
rozwiązanie działa o około 100 000 operacjiO(log n)
na sekundę mniej niż @paxdiablo na liczbach losowych. Podczas projektowania algorytmu zawsze najpierw sortuj. (Z wyjątkiem sytuacji, gdy wiesz, co robisz i masz testy porównawcze, które Cię wspierają.)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))
W przypadku tablic posortowanych (wyszukiwanie liniowe)
Wszystkie dotychczasowe odpowiedzi koncentrują się na przeszukiwaniu całej tablicy. Biorąc pod uwagę, że twoja tablica jest już posortowana i tak naprawdę chcesz tylko najbliższej liczby, jest to prawdopodobnie najszybsze rozwiązanie:
Zauważ, że algorytm można znacznie ulepszyć, np. Używając drzewa binarnego.
źródło
a[i]
lubi[0]
.Wszystkie rozwiązania są zbyt zaawansowane.
To jest tak proste, jak:
źródło
W rozwiązaniu tym zastosowano kwantyfikator egzystencjalny ES5
Array#some
, który umożliwia zatrzymanie iteracji w przypadku spełnienia warunku.W przeciwieństwie do tego
Array#reduce
, nie ma potrzeby iteracji wszystkich elementów dla jednego wyniku.Wewnątrz wywołania zwrotnego pobierana jest
delta
wartość bezwzględna między wartością wyszukaną a rzeczywistąitem
i porównywana z ostatnią deltą. Jeśli jest większy lub równy, iteracja zatrzymuje się, ponieważ wszystkie inne wartości z ich deltami są większe niż wartość rzeczywista.Jeśli
delta
w wywołaniu zwrotnym jest mniejszy, to do wyniku przypisywana jest aktualna pozycja idelta
zapisywana wlastDelta
.Na koniec brane są mniejsze wartości z równymi deltami, jak w poniższym przykładzie
22
, co skutkuje2
.Jeśli istnieje priorytet większych wartości, kontrola delta musi zostać zmieniona z:
do:
Dałoby
22
to wynik42
(priorytet większych wartości).Ta funkcja wymaga posortowanych wartości w tablicy.
Kod z priorytetem mniejszych wartości:
Kod z priorytetem większych wartości:
źródło
closestValue([ 2, 2, 42, 80 ], 50) === 2
ES6
Działa z tablicami posortowanymi i niesortowanymi
Liczby liczb całkowitych i zmiennoprzecinkowych, mile widziane ciągi znaków
Przykłady:
źródło
Nie wiem, czy mam odpowiedzieć na stare pytanie, ale ponieważ ten post pojawia się jako pierwszy w wyszukiwarce Google, miałem nadzieję, że wybaczysz mi dodanie tutaj mojego rozwiązania i mojego 2c.
Będąc leniwy, nie mogłem uwierzyć, że rozwiązaniem na to pytanie będzie PĘTLA, więc poszukałem trochę więcej i wróciłem z funkcją filtru :
To wszystko !
źródło
goog.math.clamp
(zamknięcie Google) tylko z tablicami i bez dbania o dolną granicę.Moja odpowiedź na podobne pytanie dotyczy również uwzględnienia powiązań i jest to w zwykłym JavaScript, chociaż nie używa wyszukiwania binarnego, więc jest to O (N), a nie O (logN):
https://stackoverflow.com/a/26429528/986160
źródło
Podoba mi się podejście z Fusion, ale jest w nim mały błąd. Tak to jest poprawne:
Jest też trochę szybszy, ponieważ wykorzystuje ulepszoną
for
pętlę.Na koniec napisałem swoją funkcję w ten sposób:
Przetestowałem to z
console.time()
i jest nieco szybszy niż druga funkcja.źródło
improved for loop
? Odwrócone pętle nie zawsze poprawiają wydajność..length
tylko raz, kiedy deklarujeszi
, podczas gdy dla tej pętli. Ale myślę, żevar i = arr.length;while (i--) {}
byłoby jeszcze szybciejwhile
. Teraz jest jeszcze szybszy.Działałoby nieco zmodyfikowane wyszukiwanie binarne w tablicy.
źródło
Dla małego zakresu najprościej jest mieć tablicę map, w której np. 80-ty wpis miałby wartość 82, aby użyć twojego przykładu. W przypadku znacznie większego, rzadkiego zakresu prawdopodobnie najlepszym rozwiązaniem jest wyszukiwanie binarne.
Za pomocą języka zapytań można wyszukiwać wartości w pewnej odległości po obu stronach wprowadzonej liczby, a następnie sortować wynikową skróconą listę. Jednak SQL nie ma dobrego pojęcia „następny” lub „poprzedni”, aby zapewnić „czyste” rozwiązanie.
źródło
Innym wariantem jest tutaj okrągły zakres łączący głowicę z palcami i akceptujemy tylko wartość minimalną na dane wejście. Pomogło mi to uzyskać wartości kodu znaków dla jednego z algorytmów szyfrowania.
źródło
źródło
Najbardziej wydajne byłoby wyszukiwanie binarne. Jednak nawet proste rozwiązania mogą zostać rozwiązane, gdy następna liczba jest dalszą zgodnością z bieżącej . Prawie wszystkie rozwiązania tutaj nie uwzględniają tego, że tablica jest uporządkowana i iteruje przez całość: /
Można to również uruchomić na nieprymitywach, np
closest(data, 21, item => item.age)
Zmień
find
na,findIndex
aby zwrócić indeks w tablicy.źródło
Aby znaleźć dwie najbliższe liczby w tablicy
źródło
Oto fragment kodu, aby znaleźć element najbliższy liczbie z tablicy o złożoności O (nlog (n)): -
Dane wejściowe: - {1,60,0, -10,100,87,56} Element: - 56 Najbliższa liczba w tablicy: - 60
Kod źródłowy (Java):
źródło