Reputation: 5708
Say I have an array that goes something like:
fruit_basket = ['apple', 'orange', 'banana', 'pear', 'banana']
I want to make an array fruits
that consists of the fruits found in fruit basket
, sorted in order of most frequently occurring fruit. (If there are ties I don't care about ordering.)
So one valid value for fruits
is:
['banana', 'orange', 'apple', 'pear']
What's the most concise way to achieve this using LoDash? I don't care about run time performance.
Upvotes: 2
Views: 2068
Reputation: 15609
Here's my take on this.
It doesn't use lodash as the question asks for. It's a vanilla alternative. I feel this could be valuable to people who land here from Google and don't want to use lodash (that's how I got here, at least).
const orderByCountAndDedupe = arr => {
const counts = new Map();
arr.forEach( item => {
if ( !counts.has(item) ) {
counts.set(item, 1);
} else {
counts.set(item, counts.get(item)+1);
}
});
return (
Array.from(counts)
.sort( (a, b) => b[1] - a[1])
.map( ([originalItem, count]) => originalItem)
);
};
Upvotes: 1
Reputation: 4414
You can count occurences using _.countBy and then use it in _.sortBy:
var counter = _.countBy(fruit_basket)
var result = _(fruit_basket).uniq().sortBy(fruit => counter[fruit]).reverse().value()
Upvotes: 0
Reputation: 318302
First you'd count the occurences
var x = _.chain(fruit_basket).countBy(); // {apple: 1, orange: 1, banana: 2, pear: 1}
Then you'd pair them and sort by the number of occurences, using reverse
to get the largest number first
var y = x.toPairs().sortBy(1).reverse(); //[["banana",2],["pear",1],["orange",1],["apple",1]]
Then you'd just map back the keys, and get the value as an array
var arr = y.map(0).value(); // ['banana', 'orange', 'apple', 'pear']
All chained together, it looks like
var arr = _.chain(fruit_basket).countBy().toPairs().sortBy(1).reverse().map(0).value();
Without loDash, something like this would do it
var fruit_basket = ['apple', 'orange', 'banana', 'pear', 'banana'];
var o = {};
fruit_basket.forEach(function(item) {
item in o ? o[item] += 1 : o[item] = 1;
});
var arr = Object.keys(o).sort(function(a, b) {
return o[a] < o[b];
});
Upvotes: 4
Reputation: 1
An approach using for
loop Array.prototype.splice()
var fruit_basket = ['apple', 'orange', 'banana', 'pear', 'banana'];
var res = [];
for (var i = 0; i < fruit_basket.length; i++) {
var index = res.indexOf(fruit_basket[i]);
// if current item does not exist in `res`
// push current item to `res`
if (index == -1) {
res.push(fruit_basket[i])
} else {
// else remove current item , set current item at index `0` of `res`
res.splice(index, 1);
res.splice(0, 0, fruit_basket[i])
}
}
console.log(res)
Upvotes: 0