Pregunta

Background

I'm attempting to check the existence of a value in array A in a second array, B. Each value is an observable number. Each observable number is contained in an observable array. The comparison always returns -1, which is known to be incorrect (insofar as values in A and B overlap). Therefore, there's something wrong with my logic or syntax, but I have not been able to figure out where.

JSBin (full project): http://jsbin.com/fehoq/190/edit

JS

//set up my two arrays that will be compared
this.scores = ko.observableArray();

//lowest is given values from another method that splices from scores
this.lowest = ko.observableArray();

//computes and returns mean of array less values in lowest
this.mean = (function(scores,i) {
    var m = 0;
    var count = 0;

    ko.utils.arrayForEach(_this.scores(), function(score) {

        if (!isNaN(parseFloat(score()))) {

            //check values
            console.log(score());

            // always returns -1
            console.log(_this.lowest.indexOf(score()));

            //this returns an error, 'not a function'
            console.log(_this.lowest()[i]());

            //this returns undefined
            console.log(_this.lowest()[i]);

            //only do math if score() isn't in lowest
            // again, always returns -1, so not a good check
            if (_this.lowest.indexOf(score())<0) {
                m += parseFloat(score());
                count += 1;
            }
        }

    });

    // rest of the math
    if (count) {
        m = m / count;
        return m.toFixed(2);
    } else {
        return 'N/A';
    }
});

Update

@Major Byte noted that mean() is calculated before anything gets pushed to lowest, hence why I get undefined. If this is true, then what might be the best way to ensure that mean() will update based on changes to lowest?

¿Fue útil?

Solución

You really just could use a computed for the mean

this.mean = ko.computed(
    function() {
      var sum  = 0;
      var count = 0;
      var n = 0;
      for(n;n < _this.scores().length;n++)
      {
        var score = _this.scores()[n];
          if (_this.lowest.indexOf(score)<0) {
            sum += parseFloat(score());
            count++;
          }
      }

      if (count > 0) {
        sum = sum / count;
        return sum.toFixed(2);
      } else {
        return 'N/A';
      }
});

this will trigger when you add to lower(), scores() and change scores().

obligatory jsfiddle.

Update:
Forgot to mention that I change something crucial as well. From you original code:

this.dropLowestScores = function() {
    ko.utils.arrayForEach(_this.students(), function(student){
        var comparator = function(a,b){
            if(a()<b()){
                return 1;
            } else if(a() > b()){
                return -1;
            } else {
                return 0;
            }
        };
        var tmp = student.scores().sort(comparator).slice(0);
        student.lowest = ko.observableArray(tmp.splice((tmp.length-2),tmp.length-1));
    });
 };

apart from moving the comparator outside of dropLowestScores function, I changed the line:

student.lowest = ko.observableArray(tmp.splice((tmp.length-2),tmp.length-1));

to

student.lowest(tmp.splice((tmp.length-2),tmp.length-1));

student.lowest is an observable array, no need to define it as an observableArray again, in fact that actually breaks the computed mean. (The correction for Drop Lowest Scores as per my previous comment is left out here).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top