3
\$\begingroup\$

The following function takes two numbers that are linked with a "user" and calculates an ID number based on that. I have been trying to make this as clean as possible, and would like some advice on how to make this more efficient. an example of the input would be "12195491" for the num and "3120" for the ts, which would output "8511"

function getidnumber(num, ts) {
            num = num.substr(4, 4);
            ts = ((ts == undefined) ? "3452" : (ts));
            var _local5 = "";
            var _local1 = 0;
            while (_local1 < num.length) {
                var _local4 = Number(num.substr(_local1, 1));
                var _local3 = Number(ts.substr(_local1, 1));
                var _local2 = String(_local4 + _local3);
                _local5 = _local5 + _local2.substr(_local2.length - 1);
                _local1++;
            }
            return("@user" + _local5);
};
\$\endgroup\$
  • 1
    \$\begingroup\$ Could you provide more background? Maybe an example of input and output? Why "3452"? Why as a string not a number? What is ts? \$\endgroup\$ – elclanrs Sep 21 '13 at 1:10
  • \$\begingroup\$ there are two numbers. a session id, and a userid that is passed to the function. "3452" is just a default id for if it is undefined. and so i can return the entire thing as a string, although i dont need to do it that way \$\endgroup\$ – riyoken Sep 21 '13 at 1:12
  • \$\begingroup\$ ts would be the userid, which is 6 numbers long. \$\endgroup\$ – riyoken Sep 21 '13 at 1:14
  • \$\begingroup\$ The best way to tell how to improve it is if you post examples of inputs and outputs that are valid as well as some invalid ones. \$\endgroup\$ – elclanrs Sep 21 '13 at 1:17
  • \$\begingroup\$ i have edited the question with an example input \$\endgroup\$ – riyoken Sep 21 '13 at 1:22
2
\$\begingroup\$

Here's a better implementation.

Used the unary + operator for number conversion.

Used null instead of undefined since it's shorter and produces the same result because of type coersion.

Avoid performing a substring operation by starting to iterate from index 4.

Cached num.length into len so that we save on property lookups when the condition is evaluated for every loop iteration.

Removed uneeded parenthesis.

Took advantage of the += operator.

Made sure that every variables were locally scoped. The _local1 variable in the selected answer isin't properly scoped.

Used a single var statement; it's a better practice to declare variables at the top of the function for readability.

Stole the % 10 idea from the other answer since I thought it was great ;)

 function getidnumber (num, ts) {
    var i = 4, 
        len = num.length,
        res = '@user';

    ts = ts == null? '3452' : ts;

    for (; i < len; i++) {
        res += (+num[i] + +ts[i - 4]) % 10;
    }

    return res;
}
\$\endgroup\$
  • \$\begingroup\$ I disagree with declaring variables at the top of the function. I find it better to declare it closer to where it will be used. It is Accepted practice to do so \$\endgroup\$ – Jeff Vanzella Sep 21 '13 at 7:10
  • \$\begingroup\$ @JeffVanzella, It all depends on the language being used. In JavaScript it's way more common to use a single var statement or at least declare the variables at the top of the function, despite variable hoisting. JSLint, one of the most popular JS code quality tool will complain about multiple var statements by default. Also, most popular librairies, such as jQuery adopted this coding practice as we can see here. There are perhaps cases where I tould tolerate it, but here there's no valid reason. \$\endgroup\$ – plalx Sep 21 '13 at 14:51
  • \$\begingroup\$ these are both great answers. \$\endgroup\$ – riyoken Sep 21 '13 at 16:54
  • \$\begingroup\$ @riyoken, Thanks! Make sure that you correct the scoping mistake in the answer you selected when you will implement the solution. _local1 is declared as global. \$\endgroup\$ – plalx Sep 21 '13 at 20:42
  • \$\begingroup\$ @plalx I fixed the "global" and up-voted your answer. Thanks! \$\endgroup\$ – dcaswell Sep 21 '13 at 21:56
1
\$\begingroup\$

I think this is a little simpler. These are the changes I'd recommend:

1) Always use a for loop if you have an initialization, test, and increment.

2) I'd prefer variable names that have meaning like _nextDigit

3) Take advantage of the fact that strings can be accessed using the array [] operator

4) Made it explicit that we are taking a single digit by using the modulus operator % 10 instead of using _local2.substr(_local2.length - 1).

5) There was too much switching between strings and numbers; only use numbers for modulus and addition.

6) I didn't rename _local5 but we should probably call it resultString or idNumber depending on what you consider it to be.

function getidnumber(num, ts) {
    num = num.substr(4, 4);
    ts = ((ts == undefined) ? "3452" : (ts));
    var _local5 = "";
    for (var _local1 = 0; _local1 < num.length; ++_local1) {
        var _nextDigit = (Number(num[_local1]) + Number(ts[_local1])) % 10;
        _local5 = _local5 + _nextDigit;
    }
    return ("@user" + _local5);
};
\$\endgroup\$
1
\$\begingroup\$

Another option using maths instead of string operations.

function getIdNumber(num, ts) {
    var r = '';
    ts = (ts === undefined ? 3452 : ts);
    for (var i = 1; i <= 1000; i *= 10) {
        r = (Math.floor(num / i) + Math.floor(ts / i)) % 10 + r;
    }
    return '@user' + r;
}

or similarly

function getIdNumber(num, ts) {
    var r = '';
    ts = (ts === undefined ? 3452 : ts);
    for (var i = 0; i < 4; i++) {
        r = (Math.floor(num) + Math.floor(ts)) % 10 + r;
        num /= 10;
        ts /= 10;
    }
    return '@user' + r;
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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