2011-01-26 22 views
15

Ho una matrice di numeri interi in javascript, [5,10,15,20,25,30,35] quando viene assegnato un numero x, come posso trovare l'elemento nell'array più vicino a quel numero?Trova il numero in un array più vicino a un determinato numero

Se il numero supera un valore, ma meno della metà del numero successivo, sceglierei il valore più basso, se fosse oltre la metà del numero successivo, sceglierei il numero più alto.

Ad esempio 7 restituisce 5, ma 8 restituisce 10. Come posso realizzare questo? Qualsiasi aiuto o consiglio sarebbe apprezzato. Ho cercato e non riesco a trovare una soluzione. Sono sicuro che questo è un po 'comune.

+5

Come al solito: cos'hai provato finora? –

+0

Possibile duplicato di [ottieni il numero più vicino dall'array] (http://stackoverflow.com/questions/8584902/get-closest-number-out-of-array) –

+0

** ottieni la distanza assoluta dal tuo punto (come Y), quindi inverti Y in scala (questo scala intorno a X === 0,5, dove Y è massimo) '(0,5 - Math.abs (0,5 - valore))/0,5;' ** – neaumusic

risposta

11

L'elenco di esempio è ordinato. Se questo è sempre il caso, quindi la ricerca binaria per il tuo numero. Se non trovi il numero esatto, fai terminare la ricerca binaria controllando i due numeri intorno a dove il numero sarebbe e restituire il più vicino. Fai attenzione ai casi limite in cui tutti i numeri sono maggiori o sono tutti più piccoli del numero di riferimento

Se l'elenco non è sempre ordinato, quindi passa attraverso l'elenco tenendo traccia del numero più grande < = il numero di destinazione e il più piccolo numero> = il numero di destinazione. Restituisce quello più vicino all'obiettivo.

In entrambe le soluzioni, è necessario decidere da che parte favorire se ad esempio si sta cercando 2 in [1, 3].

0

Assumendo che la matrice sia ordinata, passare attraverso ciascuna coppia adiacente di numeri interi nella matrice. Per ogni coppia (diciamo "5 e 10" o "20 e 25"), prova se x si trova tra di loro e, in tal caso, restituisci il valore più vicino a x (con un pregiudizio verso quello inferiore) .

È inoltre necessario un caso speciale per quando x è inferiore al primo numero (restituisce il primo numero) o maggiore dell'ultimo numero (restituisce l'ultimo numero).

Se la matrice non è ordinata, ordinarla prima.

+2

Bene se l'array è ordinato , puoi semplicemente fare una ricerca binaria (o praticamente qualsiasi altra ricerca) per trovare i due numeri più vicini ... –

+0

@belisarius Che cosa stai cercando di fare? – marcog

+0

@marcog Stavo rispondendo a un commento precedente, ma ero sparito ... lo cancellerei –

5

Creare un array temporaneo delle stesse dimensioni dell'array originale e popolarlo con le differenze tra x e l'elemento dell'array.

Per esempio, sia la matrice temporanea sia temperatura [], e l'array originale sia un []:

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

Poi, restituire il dell'indice del valore minimo nella temperatura [] all'utente .

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]; 
} 

Se si utilizza un approccio funzionale è applicabile, allora è possibile associare il set di tuple di (valore, distanza) poi ridurre quell'insieme di tuple alla tupla con la più piccola distanza. Restituiamo il valore in questa tupla.

Per spiegare l'utilizzo di _.map. Si associano tutti i valori della matrice ai nuovi valori e la funzione restituirà la matrice di nuovi valori. In questo caso una serie di tuple.

Per spiegare l'utilizzo di _.reduce. Si riduce la matrice a un singolo valore. Si passa in un array e un memo. Il memo è il tuo "contatore corrente" mentre ti muovi attraverso l'array.In questo caso controlliamo se la tupla corrente è più vicina al memo e se è così, rendila il memo. Alla fine restituiamo il memo.

Il frammento di codice di cui sopra si basa su underscore.js per rimuovere la parte fondamentale di stile funzionale javascript

+0

Risposta stupenda .. grazie .. tagliata e incollata, funziona a meraviglia! –

+0

Come nota a margine, lanciando in Lodash un elenco di ~ 200 elementi, Lodash esegue ~ 1.5 volte meglio (~ 45K ops/sec) rispetto alla versione di sottolineatura (~ 29K ops/sec). –

+0

BTW, il _.reduce può essere scambiato per un ordinamento numerico sulla matrice "tuples"; tuttavia, ciò non ha prestazioni altrettanto buone. Allo stesso modo, l'uso di un oggetto/hash al posto delle tuple è più leggibile, ma si comporta male. –

0

ho creato la mia funzione in quanto non ho potuto trovare qualsiasi che soddisfi le mie requeriments.

16

Probabilmente la cosa più semplice da fare è ordinare in base alla distanza dal valore di riferimento x, quindi prendere il primo elemento.

Il Array.prototype.sort() integrato può eseguire una funzione di confronto che verrà richiamata per coppie di valori dall'array. Quindi la chiave è semplicemente passare in una funzione di confronto che confronta i due valori in base alla loro distanza dal valore di riferimento 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]; 

Vai a questa semplice demo.

+1

Pollice su. Soluzione molto elegante –

Problemi correlati