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\$
    – Austin Yun
    Aug 5, 2011 at 12:16
  • \$\begingroup\$ @Austin - Yes you do need it. Try removing it and see what happens. \$\endgroup\$ 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\$
    – Austin Yun
    Aug 8, 2011 at 16:59
  • \$\begingroup\$ @Austin - I believe that it will normally be the global object. \$\endgroup\$ Aug 8, 2011 at 17:18
  • \$\begingroup\$ @ChaosPandion: interesting approach with zip, to make tuples :-) \$\endgroup\$
    – r10y
    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\$
    – kyrill
    Apr 12, 2017 at 0:14
  • 1
    \$\begingroup\$ lol, i do now..... it's been a long day. \$\endgroup\$
    – r10y
    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\$
    – Jamal
    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\$
    – kyrill
    Apr 13, 2017 at 21:51
  • \$\begingroup\$ cool, updated my answer to reflect your feedback. thanks. \$\endgroup\$
    – r10y
    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.

Not the answer you're looking for? Browse other questions tagged or ask your own question.