0

I've been challenging myself with solving this in pure functional programming style, in Javascript. The problem is this:

Input:

var src = [{n:3, x:2}, {n:6, x:1}, {n:2, x:0}, {n:10, x:5}, {n:5, x:2}, {n:1, x:44}];

Problem definition:

Group the items in the src array using a either a predicate or a hash function and sum the item.x values for each group. For example, in the output I pasted the grouping is the remainder division of item.n with 2

Output:

var trgt = [
  {sum:48, items: [{n:3, x:2}, {n:5, x:2}, {n:1, x:44}]},
  {sum:6, items: [{n:6, x:1}, {n:2, x:0}, {n:10, x:5}]}
]

The goal here is to find as pure a functional programming solution as possible.

Here is my solution

function moduloTwo(val) {
  return (val.n % 2);
}
function makeObjectAndAdd(hashFn) {
  return function (result, curr) {
    if (result[hashFn(curr)] === undefined) {
      result[hashFn(curr)] = {sum: 0, items: []};
    }
    var newObj = result[hashFn(curr)];
    newObj.items.push(curr);
    newObj.sum += curr.x;

    return result;
  };
}

var result = src.reduce(makeObjectAndAdd(moduloTwo), {});

I feel that it could be made to be more "functional".

Thanks!

5
  • the link points to the output, not your solution. output is not "functional". Code is. Commented Dec 3, 2014 at 7:30
  • You should paste the relevant code into the question directly, not only a link to it. Maybe the linked site is not reachable (anymore) and then the question couldn't be answered or makes no sense at all :) Commented Dec 3, 2014 at 7:33
  • Changed link to point to code. Commented Dec 3, 2014 at 7:33
  • I don't see the point of isDividedByTwo as a separate function. It should be called isEven and could be simply return !(val%2) since the name infers that it will return a boolean. Commented Dec 3, 2014 at 7:34
  • @RobG Like I said, you can either return a predicate or a hash function. For example, what if you would want to group by the result of %3? It wouldn't work with true/false. At-least not for this solution. I agree that the function name is misleading though. Commented Dec 3, 2014 at 7:37

1 Answer 1

2

You can write your code more functionally using Ramda.js as follows:

  1. Given an input:

    var input = [
        { n:  3, x:  2 },
        { n:  6, x:  1 },
        { n:  2, x:  0 },
        { n: 10, x:  5 },
        { n:  5, x:  2 },
        { n:  1, x: 44 }
    ];
    
  2. We first separate them into odd and even groups based on the property n:

    var oddN = R.compose(odd, R.prop("n"));
    
    var groups = R.groupBy(oddN, input);
    
    function odd(n) {
        return n % 2 === 1;
    }
    
  3. Then we get the values of all the groups, pluck the x property of each item and summate:

    var output = R.map(count, R.values(groups));
    
    function count(items) {
        return {
            sum:   R.sum(R.pluck("x", items)),
            items: items
        };
    }
    

See the online demo for yourself: http://bit.ly/1IawqzD

Sign up to request clarification or add additional context in comments.

3 Comments

I like Ramda a lot. I talk about it when explaining Functional Programming to Javascript devs
I don't like Ramda, but it's the least bad functional library we've got.
Within the confides of JavaScript I think it does a good job.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.