I have a function that sorts an array of integers by their digits sum, in case of equal digit sum than it sort by the numbers values. This is the function:
function s(g){
var r=0;
while(g)r+=g%10,g/=10;
return r;
}
function digitalSumSort(a) {
a.sort(function(x,y){
return s(x)!=s(y)?s(x)-s(y):x-y;
});
return a;
}
It sometimes works ok, but it failed at this test data:
Input: [100, 22, 4, 11, 31, 103]
Output: [100, 11, 31, 4, 22, 103]
Expected Output: [100, 11, 4, 22, 31, 103]
I couldn't figure out why it does that, and how to fix it?
Note: it is important that the code contains as least as possible characters!
Edit:
This question has already been answered but I recently made the same mistake and thought of this. Is there a way to make a var
act as an integer
(instead of a double
) when given a numeric value. I learned the trick with using floor, but sometimes I just want integer
operations instead of double
(with some systems they are faster, and I may have other reasons).
The main problem is with the s
function, because it continues looping and collecting values when g is fraction.
In addition, instead of calculating the values while sorting, you can use a Schwartzian transform aka decorate-sort-undecorate. You create an array with the computed values you'll use to sort, sort the array, than map back to the original values.
function s(g) {
var r = 0;
while (g) r += g % 10, g = Math.floor(g/10); // round g down to skip redundent loops when g is a fraction
return r;
}
function digitalSumSort(a) {
return a
.map(function(n) { // create an array with theorigina and the computed values
return [s(n), n];
})
.sort(function(a, b) {
return a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]; // sort by the computed or original values
})
.map(function(n) { // get back an array of the original values
return n[1];
});
}
console.log(digitalSumSort([100, 22, 4, 11, 31, 103])); // [100, 11, 4, 22, 31, 103]