1
\$\begingroup\$

How would I accomplish the same thing in a functional paradigm?

Player.prototype.d2 = function(ratingList, rdList) {
    var tempSum = 0;
    for (var i = 0; i < ratingList.length; i++) {
        var tempE = this.e(ratingList[i], rdList[i]);
        tempSum += Math.pow(this.g(rdList[i]), 2) * tempE * (1 - tempE);
    }
    return 1 / Math.pow(q, 2) * tempSum;
};
\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

I think something like this will work for you.

Array.prototype.zip = function(other) {
    if (!Array.prototype.isPrototypeOf(other)) {
            throw new TypeError('Expecting an array dummy!');
    }
    if (this.length !== other.length) {
            throw new Error('Must be the same length!');
    }
    var r = [];
    for (var i = 0, length = this.length; i < length; i++) {
        r.push([this[i], other[i]]);    
    }
    return r;
};

Player.prototype.d2 = function (ratingList, rdList) {
    var self = this;
    return 1 / Math.pow(q, 2) *
        ratingList
        .zip(rdList)
        .map(function (elem) {
            var tempE = self.e(elem[0], elem[1]);
            return Math.pow(self.g(elem[1]), 2) * tempE * (1 - tempE);
        })
        .reduce(function (acc, value) {
            return acc + value;
        });
};
\$\endgroup\$
6
  • \$\begingroup\$ Do you actually need var self = this? I haven't had to use that anywhere else so far. \$\endgroup\$ Commented Aug 5, 2011 at 12:16
  • \$\begingroup\$ @Austin - Yes you do need it. Try removing it and see what happens. \$\endgroup\$ Commented Aug 6, 2011 at 18:09
  • \$\begingroup\$ I'm guessing it's because inside the map function, this would refer to uh... Array.prototype? \$\endgroup\$ Commented Aug 8, 2011 at 16:59
  • \$\begingroup\$ @Austin - I believe that it will normally be the global object. \$\endgroup\$ Commented Aug 8, 2011 at 17:18
  • \$\begingroup\$ @ChaosPandion: interesting approach with zip, to make tuples :-) \$\endgroup\$ Commented Apr 12, 2017 at 0:09
1
\$\begingroup\$

I think this is essentially what you're looking for, if I'm not mistaken:

Player.prototype.d2 = function(ratingList, rdList) {
    return  Math.pow(q, -2) * ( 
        ratingList.reduce( ( sum, val, idx ) => {
            let tempE = this.e( val, rdList[idx] );
            return sum + Math.pow( this.g(rdList[idx]), 2 ) * tempE * ( 1 - tempE ); 
        }, 0)
    );
};

We start out with an anonymous function for d2, whose body is simply a return of the entire functional expression, which uses the Array.prototype.reduce function to compose a sum.

I've chosen to use ES6 so I can maintain scope this throughout my entire function.

Reduce explained on MDN and you should checkout Arrow functions.

One thing to note: a for loop is more performant than functional equivalents.

\$\endgroup\$
5
  • \$\begingroup\$ Do you realize this question is almost six years old? \$\endgroup\$ Commented Apr 12, 2017 at 0:14
  • 1
    \$\begingroup\$ lol, i do now..... it's been a long day. \$\endgroup\$ Commented Apr 12, 2017 at 0:16
  • 1
    \$\begingroup\$ Actually, I like this because the accepted answer is a code-only answer, which we consider low-quality here. It only gets a pass because it's old and accepted. \$\endgroup\$ Commented Apr 12, 2017 at 1:34
  • \$\begingroup\$ @r10y It's actually 1 / Math.pow(q, 2) …, which could be written as Math.pow(q, -2) …. Also a little detail – you're missing a semicolon after return. \$\endgroup\$ Commented Apr 13, 2017 at 21:51
  • \$\begingroup\$ cool, updated my answer to reflect your feedback. thanks. \$\endgroup\$ Commented Apr 13, 2017 at 23:33

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.