Flatten/Un-flatten (v4)

Revision 4 of this benchmark created on


Setup

var unflatten1 = function(data) {
        "use strict";
        if (Object(data) !== data || Array.isArray(data))
            return data;
        var result = {}, cur, prop, idx, last, temp;
        for(var p in data) {
            cur = result, prop = "", last = 0;
            do {
                idx = p.indexOf(".", last);
                temp = p.substring(last, idx !== -1 ? idx : undefined);
                cur = cur[prop] || (cur[prop] = (!isNaN(parseInt(temp)) ? [] : {}));
                prop = temp;
                last = idx + 1;
            } while(idx >= 0);
            cur[prop] = data[p];
        }
        return result[""];
    }
    var flatten1 = function(data) {
        var result = {};
        function recurse (cur, prop) {
            if (Object(cur) !== cur) {
                result[prop] = cur;
            } else if (Array.isArray(cur)) {
                 for(var i=0, l=cur.length; i<l; i++)
                     recurse(cur[i], prop ? prop+"."+i : ""+i);
                if (l == 0)
                    result[prop] = [];
            } else {
                var isEmpty = true;
                for (var p in cur) {
                    isEmpty = false;
                    recurse(cur[p], prop ? prop+"."+p : p);
                }
                if (isEmpty)
                    result[prop] = {};
            }
        }
        recurse(data, "");
        return result;
    }
    
    ////
    
    var flatten2 = (function (isArray, wrapped) {
        return function (table) {
            return reduce("", {}, table);
        };
    
        function reduce(path, accumulator, table) {
            if (isArray(table)) {
                var length = table.length;
    
                if (length) {
                    var index = 0;
    
                    while (index < length) {
                        var property = path + "[" + index + "]", item = table[index++];
                        if (wrapped(item) !== item) accumulator[property] = item;
                        else reduce(property, accumulator, item);
                    }
                } else accumulator[path] = table;
            } else {
                var empty = true;
    
                if (path) {
                    for (var property in table) {
                        var item = table[property], property = path + "." + property, empty = false;
                        if (wrapped(item) !== item) accumulator[property] = item;
                        else reduce(property, accumulator, item);
                    }
                } else {
                    for (var property in table) {
                        var item = table[property], empty = false;
                        if (wrapped(item) !== item) accumulator[property] = item;
                        else reduce(property, accumulator, item);
                    }
                }
    
                if (empty) accumulator[path] = table;
            }
    
            return accumulator;
        }
    }(Array.isArray, Object));
    
    var unflatten2 = function (table) {
        var result = {};
    
        for (var path in table) {
            var cursor = result, length = path.length, property = "", index = 0;
    
            while (index < length) {
                var char = path.charAt(index);
    
                if (char === "[") {
                    var start = index + 1,
                        end = path.indexOf("]", start),
                        cursor = cursor[property] = cursor[property] || [],
                        property = path.slice(start, end),
                        index = end + 1;
                } else {
                    var cursor = cursor[property] = cursor[property] || {},
                        start = char === "." ? index + 1 : index,
                        bracket = path.indexOf("[", start),
                        dot = path.indexOf(".", start);
    
                    if (bracket < 0 && dot < 0) var end = index = length;
                    else if (bracket < 0) var end = index = dot;
                    else if (dot < 0) var end = index = bracket;
                    else var end = index = bracket < dot ? bracket : dot;
    
                    var property = path.slice(start, end);
                }
            }
    
            cursor[property] = table[path];
        }
    
        return result[""];
    }
    
    ////
    
    // large test data
    var data = {"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0],"foo5":{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0],"foo5":{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},"bar5":[{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]}]},"bar5":[{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0],"foo5":{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},"bar5":[{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]}]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0],"foo5":{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},"bar5":[{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]}]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0],"foo5":{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},"bar5":[{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]}]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0],"foo5":{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},"bar5":[{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]}]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0],"foo5":{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},"bar5":[{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]},{"foo0":1,"bar0":false,"foo2":-99999,"bar2":true,"foo3":10002525.10002525,"bar3":"test","foo4":"hello world hello world hello world hello world","bar4":[1,2,3,4,5,6,7,8,9,0]}]}]};
        
        var data_1 = flatten1(data);
        var data_2 = flatten2(data);

Test runner

Ready to run.

Testing in
TestOps/sec
Current Flatten
flatten1(data);
ready
Current unflatten
unflatten1(data_1);
ready
Test flatten
flatten2(data);
ready
Test unflatten
unflatten2(data_2);
ready

Revisions

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