У меня есть число от минус 1000 до плюс 1000, и у меня есть массив с числами в нем. Как это:
[2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
Я хочу, чтобы число, которое я получил, изменилось до ближайшего номера массива.
Например, я получаю 80
номер, который хочу получить 82
.
javascript
arrays
новичек
источник
источник
x
, пройтись по массиву один за другим, сравнитьi
с текущим числом в массиве, если разница между ним иi
меньше, чем текущее значение вx
, установитьx
текущий номер массива. По окончанииx
имеет номер, ближайший кi
массиву.Ответы:
Версия ES5:
источник
goal
к сокращению, вы должны ссылаться на него из глобальной области видимости.Вот псевдокод, который должен быть преобразован в любой процедурный язык:
Он просто вычисляет абсолютные различия между данным числом и каждым элементом массива и возвращает один из них с минимальной разницей.
Для значений примера:
В качестве подтверждения концепции вот код Python, который я использовал, чтобы показать это в действии:
И, если вам действительно это нужно в Javascript, см. Ниже полный файл HTML, который демонстрирует функцию в действии:
Теперь имейте в виду, что могут быть возможности для повышения эффективности, если, например, ваши элементы данных отсортированы (это может быть выведено из примеров данных, но вы не указали это явно). Например, вы можете использовать двоичный поиск, чтобы найти ближайший элемент.
Вам также следует помнить, что, если вам не нужно делать это много раз в секунду, повышение эффективности будет в основном незаметным, если ваши наборы данных не получат намного больше.
Если вы действительно хотите попробовать его таким образом (и может гарантировать массив отсортирован в порядке возрастания), это хорошая отправная точка:
В основном он использует брекетинг и проверку среднего значения, чтобы уменьшить пространство решения вдвое для каждой итерации, классический
O(log N)
алгоритм, тогда как последовательный поиск, приведенный вышеO(N)
:Как уже говорилось, это не должно иметь большого значения для небольших наборов данных или для вещей, которые не должны быть ослепительно быстрыми, но это вариант, который вы, возможно, захотите рассмотреть.
источник
ES6 (2015) Версия:
Для повторного использования вы можете использовать функцию карри, которая поддерживает заполнители ( http://ramdajs.com/0.19.1/docs/#curry или https://lodash.com/docs#curry ). Это дает большую гибкость в зависимости от того, что вам нужно:
источник
Рабочий код, как показано ниже:
источник
Работает с несортированными массивами
Хотя здесь было несколько хороших решений, JavaScript - гибкий язык, который дает нам инструменты для решения проблемы различными способами. Конечно, все зависит от вашего стиля. Если ваш код более функциональный, вы найдете подходящий вариант сокращения , то есть:
Тем не менее, некоторые могут найти это трудно читать, в зависимости от их стиля кодирования. Поэтому я предлагаю новый способ решения проблемы:
В отличие от других подходов, использующих минимальное значение
Math.min.apply
, этот не требуетarr
сортировки входного массива. . Нам не нужно заботиться об индексах или сортировать их заранее.Я объясню код построчно для ясности:
arr.map(function(k) { return Math.abs(k - x) })
Создает новый массив, по существу сохраняя абсолютные значения заданных чисел (число вarr
) минус входное число (x
). Далее мы будем искать наименьшее число (которое также ближе к входному номеру)Math.min.apply(Math, indexArr)
Это законный способ найти наименьшее число в массиве, который мы только что создали (ничего более)arr[indexArr.indexOf(min)]
Это, пожалуй, самая интересная часть. Мы нашли наше наименьшее число, но мы не уверены, должны ли мы добавить или вычесть начальное число (x
). Это потому, что мы привыклиMath.abs()
находить разницу. Тем не менее,array.map
создает (логически) карту входного массива, сохраняя индексы в том же месте. Поэтому, чтобы найти ближайшее число, мы просто возвращаем индекс найденного минимума в данном массивеindexArr.indexOf(min)
.Я создал мусорное ведро, демонстрирующее это.
источник
3n
и это ES5, даже если вы отвечаете в 2016 году, и другие решения просто хороши, хотя этот нуб, который задал этот вопрос, явно не был программистом в то время.O(n)
проверил цифры для вас, и ваше решение работает со скоростью примерно 100 тыс. Операций в секунду, что меньше @paxdiabloO(log n)
для случайных чисел. При разработке алгоритма всегда сортируйте сначала, говорят они. (За исключением случаев, когда вы знаете, что делаете, и у вас есть ориентиры, чтобы поддержать вас.)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))
Для отсортированных массивов (линейный поиск)
Все ответы пока сосредоточены на поиске по всему массиву. Учитывая, что ваш массив уже отсортирован, и вы действительно хотите только ближайший номер, это, вероятно, самое быстрое решение:
Обратите внимание, что алгоритм может быть значительно улучшен, например, используя двоичное дерево.
источник
a[i]
илиi[0]
.Все решения перегружены.
Это так просто, как:
источник
В этом решении используется экзистенциальный квантификатор ES5
Array#some
, который позволяет остановить итерацию, если выполняется условие.Противоположность
Array#reduce
этому, не нужно повторять все элементы для одного результата.Внутри обратного вызова, абсолютное значение
delta
между искомым значением и фактическимitem
берется и сравнивается с последней дельтой. Если больше или равно, итерация останавливается, потому что все другие значения с их дельтами больше, чем фактическое значение.Если
delta
в обратном вызове меньше, то фактический элемент присваивается результату иdelta
сохраняется вlastDelta
.Наконец, берутся меньшие значения с равными дельтами, как в приведенном ниже примере
22
, что приводит к2
.Если есть приоритет больших значений, дельта-проверка должна быть изменена с:
чтобы:
Это дало бы
22
результат42
(Приоритет больших значений).Эта функция нуждается в отсортированных значениях в массиве.
Код с приоритетом меньших значений:
Код с приоритетом больших значений:
источник
closestValue([ 2, 2, 42, 80 ], 50) === 2
ES6
Работает с отсортированными и несортированными массивами
Числа Целые числа и числа с плавающей запятой, Строки приветствуются
Примеры:
источник
Я не знаю, должен ли я ответить на старый вопрос, но так как это сообщение появляется первым в поиске Google, я надеялся, что вы простите мне добавление моего решения и моего 2c здесь.
Будучи ленивым, я не мог поверить, что решением этого вопроса будет LOOP, поэтому я поискал немного больше и вернулся с функцией фильтра :
Вот и все !
источник
goog.math.clamp
(закрытие Google) только с массивами и без заботы о нижней границе.Мой ответ на аналогичный вопрос также учитывает связи, и он написан на простом Javascript, хотя он не использует бинарный поиск, поэтому это O (N), а не O (logN):
https://stackoverflow.com/a/26429528/986160
источник
Мне нравится подход от Fusion, но есть небольшая ошибка. Вот так это правильно:
Это также немного быстрее, потому что он использует улучшенный
for
цикл.В конце я написал свою функцию так:
Я проверил это с,
console.time()
и это немного быстрее, чем другие функции.источник
improved for loop
? Обратные циклы не всегда улучшают производительность..length
только один раз, когда объявляетеi
, тогда как для этого цикла. Но я думаю,var i = arr.length;while (i--) {}
что будет еще быстрееwhile
. Теперь это еще быстрее.Слегка измененный двоичный поиск в массиве будет работать.
источник
Для небольшого диапазона самая простая вещь - это иметь массив карт, где, например, 80-я запись будет иметь значение 82, чтобы использовать ваш пример. Для гораздо большего, разреженного диапазона, вероятно, стоит пойти бинарным поиском.
С помощью языка запросов вы можете запросить значения на некотором расстоянии по обе стороны от вашего входного номера, а затем отсортировать полученный список. Но у SQL нет хорошего понятия «следующий» или «предыдущий», чтобы дать вам «чистое» решение.
источник
В другом варианте мы имеем круговой диапазон, соединяющий головку с носком и принимающий только минимальное значение для данного входа. Это помогло мне получить значения кодов символов для одного из алгоритмов шифрования.
источник
источник
Наиболее эффективным будет бинарный поиск. Однако даже простые решения могут выйти, когда следующее число будет дальше совпадать с текущим . Почти все решения здесь не принимают во внимание, что массив упорядочен и повторяется, хотя все это: /
Это может быть выполнено и для не примитивов, например
closest(data, 21, item => item.age)
Перейдите
find
наfindIndex
возврат индекса в массиве.источник
Найти два ближайших числа в массиве
источник
Вот фрагмент кода, чтобы найти ближайший элемент к числу из массива в Сложности O (nlog (n)): -
Ввод: - {1,60,0, -10,100,87,56} Элемент: - 56 Ближайшее число в массиве: - 60
Исходный код (Java):
источник