Snake to Camel Case

JavaScript performance comparison

Test case created by jdeherrera

Preparation code


      
      <script>
Benchmark.prototype.setup = function() {
  const MATCH_REGEX = /[-_]+(.)?/g;
  
  function convertMatch(match, char) {
    return char ? char.toUpperCase() : '';
  };
  
  function convertStringToCamelCase(value) {
    const converted = value.replace(MATCH_REGEX, convertMatch);
  
    return converted.substr(0, 1).toLowerCase() + converted.substr(1);
  }
  
  const props = Array.from({ length: 20 }, (v, i) => 'prop_num_' + i);
  const data = Array
    .from({length: 1000}, (v, i) => i)
    .map(i => {
      const obj = {};
      props.forEach(prop => {
        obj[prop] = prop;
      });
      return obj;
    });

};
</script>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in CCBot 2.0.0 / Other 0.0.0
Test Ops/sec
Copy object one key at a time, no key transform
function copyObject(value) {
    return Object.keys(value).reduce((acc, key) => {
        acc[key] = value[key];

        return acc;
    }, {});
}

copyObject(data);
pending…
Copy object one key at a time, key transformed using native toUpperCase function
function copyObject(value) {
    return Object.keys(value).reduce((acc, key) => {
        acc[key.toUpperCase()] = value[key];

        return acc;
    }, {});
}

copyObject(data);
pending…
Copy object one key at a time, key transformed using RegEx transform function
function copyObject(value) {
    return Object.keys(value).reduce((acc, key) => {
        acc[convertStringToCamelCase(key)] = value[key];

        return acc;
    }, {});
}

copyObject(data);
pending…
Copy object with recursive key transform of object and array properties
function getType(value) {
  switch (Object.prototype.toString.call(value)) {
    case '[object Object]':
      return [ true, false, false ];

    case '[object Array]':
      return [ false, true, false ];
    
    case '[object String]':
      return [ false, false, true ];

    default:
      return [ false, false, false ];
  }
}


function toCamelCase(value) {
  const [ isObject, isArray, isString ] = getType(value);

  if (isArray) {
    return value.map(arrayValue => {
      const [ isObject, isArray ] = getType(value);
      
      return isObject || isArray ? toCamelCase(arrayValue) : arrayValue;
    });
  }

  if (isObject) {
    return Object.keys(value).reduce((acc, key) => {
      const [ isObject, isArray ] = getType(value[key]);

      acc[convertStringToCamelCase(key)] = isObject || isArray ? toCamelCase(value[key]) : value[key];

      return acc;
    }, {});
  }

  if (isString) {
    return convertStringToCamelCase(value);
  }

  return value;
}

toCamelCase(data);
pending…
Open source library humps
var _processKeys = function (convert, obj, options) {
    if (!_isObject(obj) || _isDate(obj) || _isRegExp(obj) || _isBoolean(obj) || _isFunction(obj)) {
        return obj;
    }

    var output,
        i = 0,
        l = 0;

    if (_isArray(obj)) {
        output = [];
        for (l = obj.length; i < l; i++) {
            output.push(_processKeys(convert, obj[i], options));
        }
    }
    else {
        output = {};
        for (var key in obj) {
            if (Object.prototype.hasOwnProperty.call(obj, key)) {
                output[convert(key, options)] = _processKeys(convert, obj[key], options);
            }
        }
    }
    return output;
};

var camelize = function (string) {
    if (_isNumerical(string)) {
        return string;
    }
    string = string.replace(/[\-_\s]+(.)?/g, function (match, chr) {
        return chr ? chr.toUpperCase() : '';
    });
    // Ensure 1st char is always lowercase
    return string.substr(0, 1).toLowerCase() + string.substr(1);
};

var toString = Object.prototype.toString;

var _isFunction = function (obj) {
    return typeof (obj) === 'function';
};
var _isObject = function (obj) {
    return obj === Object(obj);
};
var _isArray = function (obj) {
    return toString.call(obj) == '[object Array]';
};
var _isDate = function (obj) {
    return toString.call(obj) == '[object Date]';
};
var _isRegExp = function (obj) {
    return toString.call(obj) == '[object RegExp]';
};
var _isBoolean = function (obj) {
    return toString.call(obj) == '[object Boolean]';
};

var _isNumerical = function (obj) {
    obj = obj - 0;
    return obj === obj;
};

var _processor = function (convert, options) {
    var callback = options && 'process' in options ? options.process : options;

    if (typeof (callback) !== 'function') {
        return convert;
    }

    return function (string, options) {
        return callback(string, convert, options);
    }
};

var camelizeKeys = function (object, options) {
    return _processKeys(_processor(camelize, options), object);
}
camelizeKeys(data);
pending…

You can edit these tests or add even more tests to this page by appending /edit to the URL.

0 Comments