2011-01-26 15 views
15

Tengo una matriz de enteros en javascript, [5,10,15,20,25,30,35] cuando se le da un número x, ¿cómo puedo encontrar el elemento en la matriz más cercana a ese número?Encontrar el número en una matriz que está más cerca de un número dado

Si el número supera el valor, pero menos de la mitad del siguiente número, elegiría el valor más pequeño, si fuera más de la mitad del siguiente número, elegiría el número más alto.

Por ejemplo, 7 devolvería 5, pero 8 regresaría 10. ¿Cómo puedo lograr esto? Cualquier ayuda o consejo sería apreciado. He buscado y no puedo encontrar una solución. Estoy seguro de que esto es algo común.

+5

Como de costumbre: ¿Qué has intentado hasta ahora? –

+0

Posible duplicado de [obtener el número más cercano fuera de la matriz] (http://stackoverflow.com/questions/8584902/get-closest-number-out-of-array) –

+0

** obtener la distancia absoluta de su punto (como Y), luego invierta esa Y a escala (esto escala alrededor de X === 0.5, donde Y es máximo) '(0.5 - Math.abs (0.5 - value))/0.5;' ** – neaumusic

Respuesta

11

Su lista de ejemplos está ordenada. Si este es siempre el caso, entonces busque su número binario. Si no encuentra el número exacto, finalice la búsqueda binaria marcando los dos números alrededor del número será y devuelva el más cercano. Tenga cuidado con los casos de borde donde todos los números son mayores o son todos más pequeños que el número de destino

Si la lista no está siempre ordenada, siga la lista llevando el mayor número < = el número objetivo y el más pequeño número> = el número objetivo. Regresa el que está más cerca del objetivo.

En cualquier solución, tendrá que decidir qué lado favorecer si, por ejemplo, está buscando 2 en [1, 3].

0

Suponiendo que la matriz está ordenada, recorra cada par adyacente de enteros en la matriz. Para cada par (digamos "5 y 10" o "20 y 25"), pruebe si x está entre ellos, y si es así, devuelva el que esté más cerca de x (con un sesgo hacia el inferior) .

También se necesitaría un caso especial para cuando x es menor que el primer número (devolver el primer número) o mayor que el último número (devolver el último número).

Si la matriz no está ordenada, ordénela primero.

+2

Bueno, si la matriz está ordenada , puedes hacer una búsqueda binaria (o casi cualquier otra búsqueda) para encontrar los dos números más cercanos ... –

+0

@belisarius ¿Qué punto estás tratando de hacer? – marcog

+0

@marcog Estaba respondiendo un comentario anterior, pero desapareció ... lo eliminaré –

5

Cree una matriz temporal del mismo tamaño que la matriz original y rellene con las diferencias entre su x y el elemento de la matriz.

Por ejemplo, dejar que la matriz temporal sea temp [], y será su matriz original a []:

temp[i]=Math.abs(x-a[i]); 

A continuación, devolver el índice del valor mínimo en temp [] para el usuario .

16
function getClosest(array, target) { 
    var tuples = _.map(array, function(val) { 
     return [val, Math.abs(val - target)]; 
    }); 
    return _.reduce(tuples, function(memo, val) { 
     return (memo[1] < val[1]) ? memo : val; 
    }, [-1, 999])[0]; 
} 

Si se utiliza un enfoque funcional es aplicable a continuación, puede asignar el conjunto de tuplas de (valor, distancia) y luego reducir ese conjunto de tuplas de la tupla con la distancia más pequeña. Devolvemos el valor en esa tupla.

Explicar el uso de _.map. Puede asignar todos los valores de su matriz a nuevos valores y la función devolverá la matriz de valores nuevos. En este caso, una matriz de tuplas.

Explicar el uso de _.reduce. Usted reduce la matriz a un solo valor. Usted pasa una matriz y una nota. La nota es su "contador de ejecución" a medida que avanza por la matriz.En este caso, verificamos si la tupla actual está más cerca que la nota y, si es así, conviértalo en la nota. Luego devolvemos la nota al final.

El fragmento de código anterior se basa en underscore.js para eliminar el quid de la cuestión de estilo funcional Javascript

+0

Respuesta impresionante ... gracias ... cortar y pegar, funciona un placer! –

+0

Como nota al margen, al incluir Lodash en una lista de ~ 200 elementos, Lodash realiza ~ 1.5x mejor (~ 45K ops/seg) que la versión de guión bajo (~ 29K ops/seg). –

+0

BTW, el _.reduce se puede intercambiar por un tipo numérico en la matriz "tuples"; sin embargo, eso no funciona tan bien. Del mismo modo, el uso de un objeto/hash en lugar de tuplas es más legible, pero también tiene un bajo rendimiento. –

0

he creado mi propia función ya que no pude encontrar ninguna que cumpla con mis requerimientos.

function closest_number(quantities, number, closest_factor) 
    { 
     if (closest_factor == 'ceil') 
     { 
      quantities.sort(function(a, b) 
       { 
        return a - b 
       } 
      ); 

      for (var i = 0; i < quantities.length; i++) 
      { 
       if (quantities[i] >= number) 
       { 
        return quantities[i]; 
       } 

       last_value = quantities[i]; 
      } 

      return last_value; 
     } 
     else if (closest_factor == 'floor') 
     { 
      quantities.sort(function(a, b) 
       { 
        return a - b 
       } 
      ); 

      min_value = quantities[0]; 

      for (var i = 0; i < quantities.length; i++) 
      { 
       if (number == quantities[i]) 
       { 
        return number; 
       } 
       else if (quantities[i] < number) 
       { 
        min_value = quantities[i]; 
       } 
       else if(quantities[i] > number) 
       { 
        return min_value; 
       }   
      } 

      return min_value; 
     } 
     else 
     { 
      return false; 
     } 
    }; 
16

Probablemente lo más fácil de hacer es ordenar en función de la distancia desde el valor de referencia x, y luego tomar el primer elemento.

El Array.prototype.sort() incorporado puede tomar una función de comparación que se llamará para pares de valores de la matriz. Entonces la clave es simplemente pasar una función de comparación que compara los dos valores en función de su distancia del valor de referencia x.

let x = 8; 
let array = [5, 10, 15, 20, 25, 30, 35]; 
let closest = array.sort((a, b) => Math.abs(x - a) - Math.abs(x - b))[0]; 

Ver este simple demo.

+1

Thumb up. Solución muy elegante. –

Cuestiones relacionadas