2014-09-15 5 views
6

Ich habe dies:in einem Array

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

Was ist besser lesbar Art und Weise die Indizes der nächsten Werte auf eine andere Variable zurück?

Zum Beispiel:

Mit Variable = 1 Sollte Rückkehr { low: 3, high: 1 }

+6

Iterate über das Array, vergleichen, Werte und Rekord Indizes? Wenn du mit "am besten" etwas Komplizierteres meinst, baue vielleicht einen Intervallbaum? http://en.wikipedia.org/wiki/Interval_tree –

+0

weniger aufwendig, aber einfach. Ich habe Array.reduce versucht, ein Objekt zurückzugeben, konnte es aber nicht. –

Antwort

3

Schnelle (O(n)) und einfach genug.

max Vorbereiten und Min-Arrays akzeptieren:

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

Lösen des Problems:

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

Schleife über das Array, um den Wert von Ihrem Variable subtrahiert, vergleichen, dann die nächsten Werte aufzeichnen. Hier ist ein kurzes Beispiel:

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

Warum ein Downvote? Sicher, das ist nicht das sauberste, aber es funktioniert! –

0

Auf diese Weise:

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

Was genau macht dies zum "besten" Weg? –

+0

Ist der eleganteste Weg, es zu tun, obwohl ich einige Ideen habe, um es zu verbessern – 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); 

Dieser Code funktioniert und Sie können die Logik des Geschehens sehen.

+2

Warum würden Sie die richtige Antwort downvote. Wer hat das abgelehnt? – brso05

-1

Für Leute, die Perl lieben, Assembler oder reguläre Ausdrücke, hier eine Lösung in der Nähe zu einem Single-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 (kleine "L") hält den Index des niedrigsten Wertes, h (Klein "H") hält den Index des höchsten Wertes. Viel Spaß :)

+1

Wer schlägt hier alle Lösungen und warum? – f6a4

+1

Ich möchte das gleiche wissen –

+1

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

2

Langsam (O(n*log(n)) und einfach:

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 könnte es zu O (n) steigern. – kornieff

+0

Ist es nicht eher 'O (n + log (n))', was im Grunde genommen 'O (n)' ist. –

+0

Hmm, ich nahm an, dass die Sortierung "O (n * log (n))" hat und die Suche "O (log (n))" Komplexität hat; also, O (n * log (n) + log (n)) = O ((n + 1) * log (n)) = O (n * log (n)) '. Wenn ich falsch liege, sortiere bitte deine Quelle. – kornieff