I need to distribute certain amounts to array of people according to their score. The rule is that their demands are met according to their position with whatever remains. In JavaScript using Lo-Dash (JSBin):
var amount = 1000,
people = [
{ name : 'Joe', score: 40, demand: 400},
{ name : 'Sue', score: 30, demand: 350},
{ name : 'Kim', score: 25, demand: 300},
{ name : 'Ron', score: 20, demand: 250}
];
function distribute(people, amount){
return _.map(_.sortBy(people,'need'),function(person){
var ration = Math.min(person.demand,amount);
amount -= ration; // This is the state (mutation) that I want to avoid
return _.assign(person,{ ration: ration})
});
}
console.log(distribute(people, amount));
Result:
[{ demand: 400, name: "Joe", ration: 400, score: 40},
{ demand: 350, name: "Sue", ration: 350, score: 30},
{ demand: 300, name: "Kim", ration: 250, score: 25},
{ demand: 250, name: "Ron", ration: 0, score: 20}]
Since the solution depends on the order, is it possible to change this code to make it purely functional?
The functional solution is a fold:
function distribute(people, amount) {
return _.foldl(_.sortBy(people, 'score'), function(result, person) {
var ration = Math.min(person.demand, result.remaining);
var resultPerson = _.assign(person, { ration: ration });
return { people: result.people.concat(resultPerson),
remaining: result.remaining - ration };
}, { people: [], remaining: amount }).people;
}