To learn Knockout JS, I'm (slowly) building a gradebook in the browser. My lastest issue involves dropping the lowest scores in an observable array. I have a student
model, which has an observable array called scores
. This array consists of observable scores, which are plain numbers.
My methodology for removing the lowest grades is as follows. First, I sort each array of scores
, high-low, then, for now, splice the end of the array, such that the two lowest numbers are stored into a new array called low
. The low
variable will be used later when I calculate the mean.
First, my current dropLowestGrades
method outright removes data from the dom, which I do not desire. Second, myObservableArray.sort()
does not appear to do any sorting! I'm not sure where to go here. Relevant script follows.
var StudentsViewModel = (function () {
function StudentsViewModel() {
var _this = this;
...
this.dropLowestScores = function() {
var low = [];
ko.utils.arrayForEach(_this.students(), function(student){
console.log(student.fullName());
student.scores().sort();
/*
student.scores().sort(function(a, b) {
return a() == b() ? 0 : (a() > b() ? 1 : -1);
});
*/
low = student.scores.splice((student.scores().length-2),student.scores().length);
console.log('low: ' + low);
return low;
});
};
I currently just bind the function to a button. For simplicity's sake, I'm hard-coding the drop to be two scores. I will later allow the user to pass in a value. Note that the button is named "Sort" right now because I was originally going to have a sort feature, then build my dropLowestScores
method on top it.
<button data-bind="click: dropLowestScores">Sort</button>
I have significantly updated my method after insights from the answers. The script below still suffers from cutting the values in my scores
array, which I do not wish to change.
this.dropLowestScores = function() {
ko.utils.arrayForEach(_this.students(), function(student){
console.log(student.fullName());
var tmp = student.scores().sort();
console.log(tmp);
student.lowest = tmp.splice((tmp.length-2),tmp.length);
console.log('student lowest: ' + student.lowest);
});
};
I changed my StudentModel
such that it now has property lowest
, which keeps track of the lowest scores when user drops grades.
var StudentModel = (function () {
function StudentModel(fullName) {
var _this = this;
this.fullName = ko.observable(fullName);
this.scores = ko.observableArray();
this.lowest = [];
...
You need to remember that functions like sort()
return a sorted list of the array, they don't actually transform the array itself.
var studentScores = student.scores().sort();
or something like -
var sortedStudentScores(function () {
return student.scores().sort();
});
And if you are sorting on a property of the score you need to use something like -
var sortFunction = // Google a JavaScript sort function
var studentScores = student.scores().sort(sortFunction);
and if you are trying to remove items splicing is correct (it transforms the array itself) otherwise you need to use something like a computed to just not add the lowest in.
Updated
var sortedStudentScores(function () {
// Set a local var equal to the sorted scores
var theseScores = student.scores().sort().splice(0);
theseScores.splice(student.scores().length-2),student.scores().length);
});