HiveBrain v1.2.0
Get Started
← Back to all entries
snippetjavascriptMinor

Check for boolean values in an object and convert them to numbers

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
booleanconvertnumbersandobjectforvaluescheckthem

Problem

I have got a an object that has values true and false for certain keys.I need to find which keys has got a boolean value and convert them to 1 and 0 respectively.Please find the code below.I wanted to check for keys in an object that has got boolean values and then convert them to numbers.Im a noob in Javascript and i got some help from fellow programmers in SO.This works but im sure there is a better way of doing this.

var obj ={
    "label":'test',
    "tel":123456,
    "settings": {
      "playback": false,
      "attachfile": true,
    },
    "setTime":true,
    "setDay":false,
    "arrSettings" :[
        'Testing',
        {"playback": false,"attachfile": true},
        {"playback": false,"attachfile": true},
        123456789
    ]
}

function changeBooleanToNumber(o){

    for(var key in o){

        if(/^boolean$/i.test(typeof o[key])){
            o[key] = Number(o[key]);
        }

        if (Object.prototype.toString.call(o[key]) === '[object Object]'){

           changeBooleanToNumber(o[key]);     

        }
        else if( Object.prototype.toString.call( o[key]) === '[object Array]' ) {

            for(var i=0;i<=o[key].length-1;i++){

                if(Object.prototype.toString.call(o[key][i]) === '[object Object]'){
                     changeBooleanToNumber(o[key]);
                }

            }

        }

   }
}

changeBooleanToNumber(obj);

Solution

Before I do anything else I feel compelled to clean up your spacing convert " to ' to consistantly use only one type of strings

var obj = {
    'label': 'test',
    'tel': 123456,
    'settings': {
        'playback': false,
        'attachfile': true,
    },
    'setTime': true,
    'setDay': false,
    'arrSettings': [
        'Testing',
        {'playback': false, 'attachfile': true},
        {'playback': false, 'attachfile': true},
        123456789
    ]
};

function changeBooleanToNumber(o) {
    for (var key in o) {
        if (/^boolean$/i.test(typeof o[key])) {
            o[key] = Number(o[key]);
        }

        if (Object.prototype.toString.call(o[key]) === '[object Object]') {
            changeBooleanToNumber(o[key]);
        } else if (Object.prototype.toString.call(o[key]) === '[object Array]') {
            for (var i = 0; i < o[key].length - 1; i++) {
                if(Object.prototype.toString.call(o[key][i]) === '[object Object]') {
                    changeBooleanToNumber(o[key]);
                }
            }
        }
    }
}

changeBooleanToNumber(obj);


Now:

-
Use +x instead of Number(x); it is shorter and faster in all cases I've ever bothered to test.

-
Don't use var inline, javascript doesn't have block scope (only function scope) so it is better to declare all necessary variables at the start of your functions.

-
Cache Object.prototype.toString to make code more readable.

-
Use toString instead of a regex test for checking for the bool type

-
simplify for loop and store the upper bound in a variable instead of computing it every time

-
Use a hasOwnProperty check on the for in loop.

This leaves me with this:

function changeBooleanToNumber(o) {
    var toString = {}.toString,
        hasOwn = {}.hasOwnProperty,
        key, 
        i,
        len;
    for (key in o) {
        if (hasOwn.call(o,key)) {
            if (toString.call(o[key]) === '[object Boolean]') {
                o[key] = +o[key];
            } else if (toString.call(o[key]) === '[object Object]') {
                changeBooleanToNumber(o[key]);
            } else if (toString.call(o[key]) === '[object Array]') {
                len = o[key].length;
                for (i = 0; i < len; i++) {
                    if(toString.call(o[key][i]) === '[object Object]') {
                        changeBooleanToNumber(o[key]);
                    }
                }
            }
        }
    }
}


This resulting code looks to me like it has too many indents. I also notice that it fails on passing in an object that is an array or contains an array of arrays. Reordering some code we can check both of those cases at the root level:

function changeBooleanToNumber(o) {
    var toString = {}.toString,
        hasOwn = {}.hasOwnProperty,
        key,
        len;
    if (toString.call(o) === '[object Object]') {
        for (key in o) {
            if (hasOwn.call(o, key)) {
                if (toString.call(o[key]) === '[object Boolean]') {
                    o[key] = +o[key];
                } else if (toString.call(o[key]) === '[object Object]') {
                    changeBooleanToNumber(o[key]);
                } else if (toString.call(o[key]) === '[object Array]') {
                    changeBooleanToNumber(o[key]);
                }
            }
        }
    } else if (toString.call(o) === '[object Array]') {
        len = o.length;
        for (key = 0; key < len; key++) {
            if (toString.call(o[key]) === '[object Boolean]') {
                o[key] = +o[key];
            } else if (toString.call(o[key]) === '[object Object]') {
                changeBooleanToNumber(o[key]);
            } else if (toString.call(o[key]) === '[object Array]') {
                changeBooleanToNumber(o[key]);
            }
        }
    }
}


However now there is a bunch of duplicate code. This can be reduced by abstracting a function:

function changeBooleanToNumberHelper(o, key) {
    var toString = {}.toString;
    if (toString.call(o[key]) === '[object Boolean]') {
        o[key] = +o[key];
    } else if (toString.call(o[key]) === '[object Object]') {
        changeBooleanToNumber(o[key]);
    } else if (toString.call(o[key]) === '[object Array]') {
        changeBooleanToNumber(o[key]);
    }
}
function changeBooleanToNumber(o) {
    var toString = {}.toString,
        hasOwn = {}.hasOwnProperty,
        key,
        len;
    if (toString.call(o) === '[object Object]') {
        for (key in o) {
            if (hasOwn.call(o, key)) {
                changeBooleanToNumberHelper(o, key);
            }
        }
    } else if (toString.call(o) === '[object Array]') {
        len = o.length;
        for (key = 0; key < len; key++) {
            changeBooleanToNumberHelper(o, key);
        }
    }
}


Here, the if statements look very similar. It turns out we can inline this helper function:

```
function changeBooleanToNumber(o, key) {
var toString = {}.toS

Code Snippets

var obj = {
    'label': 'test',
    'tel': 123456,
    'settings': {
        'playback': false,
        'attachfile': true,
    },
    'setTime': true,
    'setDay': false,
    'arrSettings': [
        'Testing',
        {'playback': false, 'attachfile': true},
        {'playback': false, 'attachfile': true},
        123456789
    ]
};

function changeBooleanToNumber(o) {
    for (var key in o) {
        if (/^boolean$/i.test(typeof o[key])) {
            o[key] = Number(o[key]);
        }

        if (Object.prototype.toString.call(o[key]) === '[object Object]') {
            changeBooleanToNumber(o[key]);
        } else if (Object.prototype.toString.call(o[key]) === '[object Array]') {
            for (var i = 0; i < o[key].length - 1; i++) {
                if(Object.prototype.toString.call(o[key][i]) === '[object Object]') {
                    changeBooleanToNumber(o[key]);
                }
            }
        }
    }
}

changeBooleanToNumber(obj);
function changeBooleanToNumber(o) {
    var toString = {}.toString,
        hasOwn = {}.hasOwnProperty,
        key, 
        i,
        len;
    for (key in o) {
        if (hasOwn.call(o,key)) {
            if (toString.call(o[key]) === '[object Boolean]') {
                o[key] = +o[key];
            } else if (toString.call(o[key]) === '[object Object]') {
                changeBooleanToNumber(o[key]);
            } else if (toString.call(o[key]) === '[object Array]') {
                len = o[key].length;
                for (i = 0; i < len; i++) {
                    if(toString.call(o[key][i]) === '[object Object]') {
                        changeBooleanToNumber(o[key]);
                    }
                }
            }
        }
    }
}
function changeBooleanToNumber(o) {
    var toString = {}.toString,
        hasOwn = {}.hasOwnProperty,
        key,
        len;
    if (toString.call(o) === '[object Object]') {
        for (key in o) {
            if (hasOwn.call(o, key)) {
                if (toString.call(o[key]) === '[object Boolean]') {
                    o[key] = +o[key];
                } else if (toString.call(o[key]) === '[object Object]') {
                    changeBooleanToNumber(o[key]);
                } else if (toString.call(o[key]) === '[object Array]') {
                    changeBooleanToNumber(o[key]);
                }
            }
        }
    } else if (toString.call(o) === '[object Array]') {
        len = o.length;
        for (key = 0; key < len; key++) {
            if (toString.call(o[key]) === '[object Boolean]') {
                o[key] = +o[key];
            } else if (toString.call(o[key]) === '[object Object]') {
                changeBooleanToNumber(o[key]);
            } else if (toString.call(o[key]) === '[object Array]') {
                changeBooleanToNumber(o[key]);
            }
        }
    }
}
function changeBooleanToNumberHelper(o, key) {
    var toString = {}.toString;
    if (toString.call(o[key]) === '[object Boolean]') {
        o[key] = +o[key];
    } else if (toString.call(o[key]) === '[object Object]') {
        changeBooleanToNumber(o[key]);
    } else if (toString.call(o[key]) === '[object Array]') {
        changeBooleanToNumber(o[key]);
    }
}
function changeBooleanToNumber(o) {
    var toString = {}.toString,
        hasOwn = {}.hasOwnProperty,
        key,
        len;
    if (toString.call(o) === '[object Object]') {
        for (key in o) {
            if (hasOwn.call(o, key)) {
                changeBooleanToNumberHelper(o, key);
            }
        }
    } else if (toString.call(o) === '[object Array]') {
        len = o.length;
        for (key = 0; key < len; key++) {
            changeBooleanToNumberHelper(o, key);
        }
    }
}
function changeBooleanToNumber(o, key) {
    var toString = {}.toString,
        hasOwn = {}.hasOwnProperty,
        len;
    if (key) {
        if (toString.call(o[key]) === '[object Boolean]') {
            o[key] = +o[key];
            return;
        }
        o = o[key];
    }
    if (toString.call(o) === '[object Object]') {
        for (key in o) {
            if (hasOwn.call(o, key)) {
                changeBooleanToNumber(o, key);
            }
        }
    } else if (toString.call(o) === '[object Array]') {
        len = o.length;
        for (key = 0; key < len; key++) {
            changeBooleanToNumber(o, key);
        }
    }
}

Context

StackExchange Code Review Q#13561, answer score: 2

Revisions (0)

No revisions yet.