2014-09-15 17 views
6

ho questo:Return Index dei valori più vicini in una matrice

var scores=[0.7, 1.05, 0.81, 0.96, 3.2, 1.23]; 

Qual è il modo più leggibile per restituire gli indici dei valori più vicini ad un'altra variabile?

Ad esempio:

Con variabile = 1 deve restituire { low: 3, high: 1 }

+6

iterare l'array, confrontare i valori e gli indici di record? Se per "migliore" intendi qualcosa di più elaborato, magari costruisci un albero ad intervalli? http://en.wikipedia.org/wiki/Interval_tree –

+0

meno elaborato, ma semplice. stavo cercando Array.reduce restituendo un oggetto ma non potevo. –

risposta

3

veloce (O(n)) e abbastanza semplice.

Preparare max e min di accettare le matrici:

var max = function (arr) { return Math.max.apply(null, arr); }; 
var min = function (arr) { return Math.min.apply(null, arr); }; 

risolvere il problema:

var nearest = function (arr, x) { 
    var l = [], h = []; 

    arr.forEach(function (v) { 
     ((v < x) && l.push(v)) || ((v > x) && h.push(v)); 
    }); 

    return { "low": arr.indexOf(max(l)), "high": arr.indexOf(min(h)) }; 
}; 

jsfiddle

0

loop sopra la matrice, sottrarre il valore dalla variabile, confrontare, quindi registrare i valori più vicini. Ecco un esempio veloce:

var value = 1; 
 
var scores = [0.7, 1.05, 0.81, 0.96, 3.2, 1.23]; 
 
var ret = {}; 
 

 
for(var i = 0, len = scores.length; i < len; i++){ 
 
    var comp = scores[i] - value; 
 
    if(comp > 0){ 
 
    if(!ret.high){ 
 
     ret.high = i; 
 
    } 
 
    else if(scores[i] < scores[ret.high]){ 
 
     ret.high = i; 
 
    } 
 
    } 
 
    else if(comp < 0){ 
 
    if(!ret.low){ 
 
     ret.low = i; 
 
    } 
 
    else if(scores[i] > scores[ret.low]){ 
 
     ret.low = i; 
 
    } 
 
    } 
 
    else{ 
 
    ret = { 
 
     low: i, 
 
     high: i 
 
    }; 
 
    break; 
 
    } 
 
} 
 

 
document.getElementById('result').innerHTML = 'high: '+ret.high+' low: '+ret.low;
<div id="result"></div>

+2

Perché un downvote? Sicuro questo non è il più pulito, ma funziona! –

0

questo modo:

var lower = function(a,b){return a.element > b.element ? b : a; }; 
var higher = function(a,b){return a.element > b.element ? a : b; }; 
var withIndex = function(element,index){ return {element: element, index: index}; }; 
var nearest = function(array, limit) { 
    var lowerValues = array.map(withIndex).filter(function(a){ return a.element<limit }); 
    var higherValues = array.map(withIndex).filter(function(a){ return a.element>limit }); 
    return { 
    low: lowerValues.reduce(higher).index, 
    high: higherValues.reduce(lower).index 
    }; 
} 
+0

Che cosa rende esattamente questo il modo "migliore"? –

+0

È il modo più elegante per farlo, anche se ho qualche idea per migliorarlo. – dseminara

-1
// for storing greater values and their indeces 
var gtVals = { 
    val : [], 
    ind : [] 
}; 

// for storing lesser values and their indeces 
var ltVals = { 
    val : [], 
    ind : [] 
} 

var scores=[0.7, 1.05, 0.81, 0.96, 3.2, 1.23]; 

function highLow(value){ 
    var val = parseFloat(value); 

     for(var i = 0; i < scores.length ; i++){ 
      if(scores[i] > val){ 
       gtVals.val.push(scores [i] - val); 
       gtVals.ind.push(i); 
      } 
     else{ 
      ltVals.val.push(val - scores[i]); 
      ltVals.ind.push(i); 
     } 

    } 
    var higherindex = gtVals.ind[gtVals.val.indexOf((Math.min.apply(Math, gtVals.val)))]; 
    var lowerindex = ltVals.ind[ltVals.val.indexOf((Math.min.apply(Math, ltVals.val)))]; 
    return { 
     low: lowerindex, 
     high : higherindex 
    }; 
} 

console.log(highLow(1)); 

http://jsfiddle.net/2q572hxj/3/

0
var scores=[0.7, 1.05, 0.81, 0.96, 3.2, 1.23]; 
var lowIndex = 0; 
var highIndex = 0; 
var currentLow = 0; 
var currentHigh = 0; 
var temp = 0; 
var variable = 2; 
for(var i = 0; i < scores.length; i++) 
{ 
    temp = variable - scores[i]; 
    if((currentLow == 0) && (temp > 0)) 
    { 
     currentLow = temp; 
    } 
    if((currentHigh == 0) && (temp < 0)) 
    { 
     currentHigh = temp; 
    } 
    if((temp >= currentHigh) && (temp <= 0)) 
    { 
     highIndex = i; 
     currentHigh = temp; 
    } 
    if((temp <= currentLow) && (temp >= 0)) 
    { 
     lowIndex = i; 
     currentLow = temp; 
    } 
} 
window.alert("Low:" + lowIndex + " High:" + highIndex); 

Questo codice funziona e puoi vedere la logica di cosa sta succedendo.

+2

Perché dovresti downvotare la risposta corretta. Chi ha downvoted questo? – brso05

-1

Per chi ama perl, assemblatore o espressioni regolari, qui una soluzione nei pressi di un singolo-liner:

var compV = 1; 
var scores=[0.7, 1.05, 0.81, 0.96, 3.2, 1.23]; 

for(var h=0,l=0,i=0,tmp=0,lV=Number.MAX_VALUE,hV=lV; i < scores.length; i++) { 
    tmp=compV-scores[i];tmp>0 && tmp<lV ? (l=i,lV=tmp) : tmp<0 && -tmp<hV ? (h=i,hV=-tmp) : 0; } 

l (minuscola "L") contiene l'indice del valore più basso, h (minuscolo "H") contiene l'indice del valore più alto. Buon divertimento :)

+1

Chi downvotes tutte le soluzioni qui e perché? – f6a4

+1

Mi piacerebbe sapere lo stesso –

+1

http://meta.stackexchange.com/questions/126829/what-is-serial-voting-and-how-does-affect-me –

2

Lento (O(n*log(n)) e semplice:

var nearest = function (arr, val) { 
    var s = arr.concat(val).sort(); 
    var i = s.indexOf(val); 

    return { "low": arr.indexOf(s[i-1]), "high": arr.indexOf(s[i+1]) }; 
}; 

jsfiddle

+0

Lazy.js potrebbe aumentarlo fino a O (n). – kornieff

+0

Non è piuttosto 'O (n + log (n))' che è fondamentalmente 'O (n)'. –

+0

Hmm, ho presunto che l'ordinamento abbia 'O (n * log (n))' e la ricerca abbia la complessità 'O (log (n))'; quindi, 'O (n * log (n) + log (n)) = O ((n + 1) * log (n)) = O (n * log (n))'. Se ho torto sull'ordinamento, per favore condividi la tua fonte. – kornieff

Problemi correlati