I am creating a function that takes in an array of unsorted integers and returns an array of the unique integers, sorted by frequency. However, if the integers have the same frequency, they will be returned in the original order of the input array. Here is my current function:
function uniqueUnionSorted(arr) {
counter = {};
for(var i=0; i<arr.length; i++) {
if (arr[i] in counter) {
counter[arr[i]] ++;
} else {
counter[arr[i]] = 1;
}
}
sortedStrings = Object.keys(counter).sort(function(a,b) {
return counter[b] - counter[a]
});
var sortedNumbers = sortedStrings.map(Number);
return sortedNumbers;
}
So for an array like this:
arr = [1, 3, 2, 1, 5, 2, 1, 4]
the function should return:
[1,2,3,5,4]
However, my function is sorting the 5 and 4 and is returning:
[1,2,3,4,5]
Please help!
The cause of this reordering is that object properties that are numerical will come out ordered when using Object.keys()
.
Instead of defining counter
as an object, use a Map
, which will retain the insertion order:
function uniqueUnionSorted(arr) {
var counter = new Map();
for(var i=0; i<arr.length; i++) {
counter.set(arr[i], (counter.get(arr[i]) || 0) + 1);
}
// Spreading the Map will produce an array of pairs
var sortedNumbers = [...counter].sort(function(a,b) {
return b[1] - a[1]; // sort by count
}).map(a => a[0]); // only keep the values, not the counts
return sortedNumbers; // Map keys retain original type, so they remain numeric
}
arr = [1, 3, 2, 1, 5, 2, 1, 4]
console.log(uniqueUnionSorted(arr));