Tengo un número de menos 1000 a más 1000 y tengo una matriz con números. Me gusta esto:
[2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
Quiero que el número que tengo cambie al número más cercano de la matriz.
Por ejemplo, obtengo el 80
número que quiero obtener 82
.
javascript
arrays
novato
fuente
fuente
x
, ir a través de la matriz una por una, comparari
con el número actual en la matriz, si la diferencia entre ella yi
es menor que el valor actual enx
, establecerx
el número de matriz actual. Cuando finaliza,x
tiene el número más cercano ai
la matriz.Respuestas:
Versión ES5:
fuente
goal
para reducir, debe hacer referencia a él desde un ámbito global.Aquí está el pseudocódigo que debe ser convertible a cualquier lenguaje de procedimiento:
Simplemente resuelve las diferencias absolutas entre el número dado y cada elemento de la matriz y le devuelve uno de los que tiene la mínima diferencia.
Para los valores de ejemplo:
Como prueba de concepto, aquí está el código de Python que usé para mostrar esto en acción:
Y, si realmente lo necesita en Javascript, consulte a continuación un archivo HTML completo que demuestra la función en acción:
Ahora tenga en cuenta que puede haber margen para mejorar la eficiencia si, por ejemplo, sus elementos de datos están ordenados (eso podría inferirse de los datos de la muestra pero no lo declara explícitamente). Podría, por ejemplo, utilizar una búsqueda binaria para encontrar el elemento más cercano.
También debe tener en cuenta que, a menos que necesite hacerlo muchas veces por segundo, las mejoras de eficiencia serán principalmente imperceptibles a menos que sus conjuntos de datos sean mucho más grandes.
Si no desea intentarlo de esa manera (y puede garantizar la matriz se ordena en orden ascendente), este es un buen punto de partida:
Básicamente utiliza el uso de corchetes y la comprobación del valor medio para reducir el espacio de la solución a la mitad para cada iteración, un
O(log N)
algoritmo clásico , mientras que la búsqueda secuencial anterior fueO(N)
:Como se dijo, eso no debería hacer una gran diferencia para los conjuntos de datos pequeños o para cosas que no necesitan ser cegadoramente rápidas, pero es una opción que puede considerar.
fuente
Versión ES6 (2015):
Para la reutilización, puede incluir una función de curry que admita marcadores de posición ( http://ramdajs.com/0.19.1/docs/#curry o https://lodash.com/docs#curry ). Esto le da mucha flexibilidad dependiendo de lo que necesita:
fuente
Código de trabajo de la siguiente manera:
fuente
Funciona con matrices sin clasificar.
Si bien se publicaron algunas buenas soluciones aquí, JavaScript es un lenguaje flexible que nos brinda herramientas para resolver un problema de muchas maneras diferentes. Todo se reduce a tu estilo, por supuesto. Si su código es más funcional, encontrará la variación de reducción adecuada, es decir:
Sin embargo, algunos pueden encontrar eso difícil de leer, dependiendo de su estilo de codificación. Por lo tanto, propongo una nueva forma de resolver el problema:
Al contrario de otros enfoques para encontrar el valor mínimo utilizando
Math.min.apply
, éste no requiere de la matriz de entradaarr
a clasificar . No necesitamos preocuparnos por los índices ni ordenarlos de antemano.Explicaré el código línea por línea para mayor claridad:
arr.map(function(k) { return Math.abs(k - x) })
Crea una nueva matriz, esencialmente almacenando los valores absolutos de los números dados (número enarr
) menos el número de entrada (x
). Luego buscaremos el número más pequeño (que también es el más cercano al número de entrada)Math.min.apply(Math, indexArr)
Esta es una forma legítima de encontrar el número más pequeño en la matriz que acabamos de crear (nada más)arr[indexArr.indexOf(min)]
Esta es quizás la parte más interesante. Hemos encontrado nuestro número más pequeño, pero no estamos seguros de si debemos sumar o restar el número inicial (x
). Eso es porque solíamosMath.abs()
encontrar la diferencia. Sin embargo,array.map
crea (lógicamente) un mapa de la matriz de entrada, manteniendo los índices en el mismo lugar. Por lo tanto, para encontrar el número más cercano, solo devolvemos el índice del mínimo encontrado en la matriz dadaindexArr.indexOf(min)
.He creado un contenedor que lo demuestra.
fuente
3n
y es ES5 a pesar de que respondiste en 2016 y otras soluciones están bien, aunque este novato que hizo esta pregunta claramente no era un programador en ese momento.O(n)
solución realiza alrededor de 100k operaciones / seg menos que @paxdiabloO(log n)
en números aleatorios. Cuando se diseña un algoritmo siempre se ordena primero, dicen. (Excepto si sabes lo que estás haciendo y tienes puntos de referencia para respaldarte.)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))
Para matrices ordenadas (búsqueda lineal)
Todas las respuestas hasta ahora se concentran en buscar en toda la matriz. Teniendo en cuenta que su matriz ya está ordenada y realmente solo desea el número más cercano, esta es probablemente la solución más rápida:
Tenga en cuenta que el algoritmo puede mejorarse enormemente, por ejemplo, utilizando un árbol binario.
fuente
a[i]
oi[0]
.Todas las soluciones están sobredimensionadas.
Es tan simple como:
fuente
Esta solución utiliza el cuantificador existencial ES5
Array#some
, que permite detener la iteración, si se cumple una condición.Opuesto a
Array#reduce
, no necesita iterar todos los elementos para un resultado.Dentro de la devolución de llamada, se toma un absoluto
delta
entre el valor buscado y el realitem
y se compara con el último delta. Si es mayor o igual, la iteración se detiene, porque todos los demás valores con sus deltas son mayores que el valor real.Si la
delta
devolución de llamada es menor, el elemento real se asigna al resultado ydelta
se guarda enlastDelta
.Finalmente, se toman valores más pequeños con deltas iguales, como en el siguiente ejemplo de
22
, que da como resultado2
.Si hay una prioridad de valores mayores, la verificación delta debe cambiarse de:
a:
Esto obtendría con
22
el resultado42
(Prioridad de valores mayores).Esta función necesita valores ordenados en la matriz.
Código con prioridad de valores más pequeños:
Código con prioridad de valores mayores:
fuente
closestValue([ 2, 2, 42, 80 ], 50) === 2
ES6
Funciona con arreglos ordenados y sin clasificar
Números enteros y flotadores, cadenas bienvenidas
Ejemplos:
fuente
No sé si se supone que debo responder una pregunta anterior, pero como esta publicación aparece primero en las búsquedas de Google, esperaba que me perdonara agregar mi solución y mi 2c aquí.
Siendo perezoso, no podía creer que la solución para esta pregunta fuera un LOOP, así que busqué un poco más y regresé con la función de filtro :
Eso es todo !
fuente
goog.math.clamp
(cierre de google) solo con matrices y sin preocuparse por el límite inferior.Mi respuesta a una pregunta similar también es responsable de los vínculos y está en Javascript simple, aunque no utiliza la búsqueda binaria, por lo que es O (N) y no O (logN):
https://stackoverflow.com/a/26429528/986160
fuente
Me gusta el enfoque de Fusion, pero hay un pequeño error. Así es correcto:
También es un poco más rápido porque utiliza el mejorado
for
bucle .Al final escribí mi función así:
Lo probé
console.time()
y es un poco más rápido que la otra función.fuente
improved for loop
? Los bucles invertidos no siempre son una mejora del rendimiento..length
solo una vez, cuando declarai
, mientras que para este ciclo. Pero creovar i = arr.length;while (i--) {}
que sería aún más rápidowhile
. Ahora es aún más rápido.Una búsqueda binaria ligeramente modificada en la matriz funcionaría.
fuente
Para un rango pequeño, lo más simple es tener una matriz de mapas, donde, por ejemplo, la 80a entrada tendría el valor 82, para usar su ejemplo. Para un rango mucho más amplio y escaso, probablemente el camino a seguir es una búsqueda binaria.
Con un lenguaje de consulta, puede buscar valores a cierta distancia a cada lado de su número de entrada y luego ordenar a través de la lista reducida resultante. Pero SQL no tiene un buen concepto de "siguiente" o "anterior", para darle una solución "limpia".
fuente
Otra variante aquí tenemos un rango circular que conecta la cabeza con los pies y acepta solo el valor mínimo para la entrada dada. Esto me ayudó a obtener valores de código de caracteres para uno de los algoritmos de cifrado.
fuente
fuente
Lo más eficiente sería una búsqueda binaria. Sin embargo, incluso las soluciones simples pueden salir cuando el siguiente número coincide más con el actual . Casi todas las soluciones aquí no tienen en cuenta que la matriz está ordenada e iterando a pesar de todo: /
Esto también se puede ejecutar en no primitivos, por ejemplo
closest(data, 21, item => item.age)
Cambie
find
afindIndex
para devolver el índice en la matriz.fuente
Para encontrar dos números más cercanos en la matriz
fuente
Aquí está el fragmento de Código para encontrar el elemento más cercano a un número de una matriz en Complejidad O (nlog (n)): -
Entrada: - {1,60,0, -10,100,87,56} Elemento: - 56 Número más cercano en la matriz: - 60
Código fuente (Java):
fuente