Deep Flatten JavaScript Object Recursively

stack247 picture stack247 · Apr 22, 2016 · Viewed 11.9k times · Source

Data:

var data = [
    {
      "id": 1,
      "level": "1",
      "text": "Sammy",
      "type": "Item",
      "items": [
        {
          "id": 11,
          "level": "2",
          "text": "Table",
          "type": "Item",
          "items": [
            {
              "id": 111,
              "level": "3",
              "text": "Dog",
              "type": "Item",
              "items": null
            },
            {
              "id": 112,
              "level": "3",
              "text": "Cat",
              "type": "Item",
              "items": null
            }
          ]
        },
        {
          "id": 12,
          "level": "2",
          "text": "Chair",
          "type": "Item",
          "items": [
            {
              "id": 121,
              "level": "3",
              "text": "Dog",
              "type": "Item",
              "items": null
            },
            {
              "id": 122,
              "level": "3",
              "text": "Cat",
              "type": "Item",
              "items": null
            }
          ]
        }
      ]
    },
    {
      "id": 2,
      "level": "1",
      "text": "Sundy",
      "type": "Item",
      "items": [
        {
          "id": 21,
          "level": "2",
          "text": "MTable",
          "type": "Item",
          "items": [
            {
              "id": 211,
              "level": "3",
              "text": "MTDog",
              "type": "Item",
              "items": null
            },
            {
              "id": 212,
              "level": "3",
              "text": "MTCat",
              "type": "Item",
              "items": null
            }
          ]
        },
        {
          "id": 22,
          "level": "2",
          "text": "MChair",
          "type": "Item",
          "items": [
            {
              "id": 221,
              "level": "3",
              "text": "MCDog",
              "type": "Item",
              "items": null
            },
            {
              "id": 222,
              "level": "3",
              "text": "MCCat",
              "type": "Item",
              "items": null
            }
          ]
        }
      ]
    },
    {
      "id": 3,
      "level": "1",
      "text": "Bruce",
      "type": "Folder",
      "items": [
        {
          "id": 31,
          "level": "2",
          "text": "BTable",
          "type": "Item",
          "items": [
            {
              "id": 311,
              "level": "3",
              "text": "BTDog",
              "type": "Item",
              "items": null
            },
            {
              "id": 312,
              "level": "3",
              "text": "BTCat",
              "type": "Item",
              "items": null
            }
          ]
        },
        {
          "id": 32,
          "level": "2",
          "text": "Chair",
          "type": "Item",
          "items": [
            {
              "id": 321,
              "level": "3",
              "text": "BCDog",
              "type": "Item",
              "items": null
            },
            {
              "id": 322,
              "level": "3",
              "text": "BCCat",
              "type": "Item",
              "items": null
            }
          ]
        }
      ]
    }
  ];

Code:

var fdr = [];
var fd = function(n) {
  if (n.items) {
    _.forEach(n.items, function (value){
      fd(value);
    });
  }

  fdr.push(n);
};
_.forEach(data, fd);
console.log(fdr);

Desired output:

var data = [
    {
      "id": 1,
      "level": "1",
      "text": "Sammy",
      "type": "Item",
      "items": []
    },
    {
      "id": 11,
      "level": "2",
      "text": "Table",
      "type": "Item",
      "items": []
    },
    {
      "id": 111,
      "level": "3",
      "text": "Dog",
      "type": "Item",
      "items": null
    },
    {
      "id": 112,
      "level": "3",
      "text": "Cat",
      "type": "Item",
      "items": null
    },
    {
      "id": 12,
      "level": "2",
      "text": "Chair",
      "type": "Item",
      "items": []
    },
    {
      "id": 121,
      "level": "3",
      "text": "Dog",
      "type": "Item",
      "items": null
    },
    {
      "id": 122,
      "level": "3",
      "text": "Cat",
      "type": "Item",
      "items": null
    },
    {
      "id": 2,
      "level": "1",
      "text": "Sundy",
      "type": "Item",
      "items": []
    },
    {
      "id": 21,
      "level": "2",
      "text": "MTable",
      "type": "Item",
      "items": []
    },
    {
      "id": 211,
      "level": "3",
      "text": "MTDog",
      "type": "Item",
      "items": null
    },
    {
      "id": 212,
      "level": "3",
      "text": "MTCat",
      "type": "Item",
      "items": null
    },
    {
      "id": 22,
      "level": "2",
      "text": "MChair",
      "type": "Item",
      "items": []
    },
    {
      "id": 221,
      "level": "3",
      "text": "MCDog",
      "type": "Item",
      "items": null
    },
    {
      "id": 222,
      "level": "3",
      "text": "MCCat",
      "type": "Item",
      "items": null
    },
    {
      "id": 3,
      "level": "1",
      "text": "Bruce",
      "type": "Folder",
      "items": []
    },
    {
      "id": 31,
      "level": "2",
      "text": "BTable",
      "type": "Item",
      "items": []
    },
    {
      "id": 311,
      "level": "3",
      "text": "BTDog",
      "type": "Item",
      "items": null
    },
    {
      "id": 312,
      "level": "3",
      "text": "BTCat",
      "type": "Item",
      "items": null
    },
    {
      "id": 32,
      "level": "2",
      "text": "Chair",
      "type": "Item",
      "items": []
    },
    {
      "id": 321,
      "level": "3",
      "text": "BCDog",
      "type": "Item",
      "items": null
    },
    {
      "id": 322,
      "level": "3",
      "text": "BCCat",
      "type": "Item",
      "items": null
    }
  ];

Conditions:

  • Object have unknowns level. Some child item may have one level down and some could have up to 5.

Questions

The fd function in the code is what I have come up with. I believe there's a 'cleaner' way to do this, just can't think of something. Plus, the function return items object, render it circular object.

JsBin: http://jsbin.com/debojiqove/2/edit?html,js,output

Is there a way to flatten object recursively with lodash or just plain JavaScript?.

Answer

Nina Scholz picture Nina Scholz · Apr 22, 2016

A solution in plain Javascript with respect to the items. It does not mutilate the source array.

function flat(r, a) {
    var b = {};
    Object.keys(a).forEach(function (k) {
        if (k !== 'items') {
            b[k] = a[k];
        }
    });
    r.push(b);
    if (Array.isArray(a.items)) {
        b.items = a.items.map(function (a) { return a.id; });
        return a.items.reduce(flat, r);
    }
    return r;
}

var data = [{ "id": 1, "level": "1", "text": "Sammy", "type": "Item", "items": [{ "id": 11, "level": "2", "text": "Table", "type": "Item", "items": [{ "id": 111, "level": "3", "text": "Dog", "type": "Item", "items": null }, { "id": 112, "level": "3", "text": "Cat", "type": "Item", "items": null }] }, { "id": 12, "level": "2", "text": "Chair", "type": "Item", "items": [{ "id": 121, "level": "3", "text": "Dog", "type": "Item", "items": null }, { "id": 122, "level": "3", "text": "Cat", "type": "Item", "items": null }] }] }, { "id": 2, "level": "1", "text": "Sundy", "type": "Item", "items": [{ "id": 21, "level": "2", "text": "MTable", "type": "Item", "items": [{ "id": 211, "level": "3", "text": "MTDog", "type": "Item", "items": null }, { "id": 212, "level": "3", "text": "MTCat", "type": "Item", "items": null }] }, { "id": 22, "level": "2", "text": "MChair", "type": "Item", "items": [{ "id": 221, "level": "3", "text": "MCDog", "type": "Item", "items": null }, { "id": 222, "level": "3", "text": "MCCat", "type": "Item", "items": null }] }] }, { "id": 3, "level": "1", "text": "Bruce", "type": "Folder", "items": [{ "id": 31, "level": "2", "text": "BTable", "type": "Item", "items": [{ "id": 311, "level": "3", "text": "BTDog", "type": "Item", "items": null }, { "id": 312, "level": "3", "text": "BTCat", "type": "Item", "items": null }] }, { "id": 32, "level": "2", "text": "Chair", "type": "Item", "items": [{ "id": 321, "level": "3", "text": "BCDog", "type": "Item", "items": null }, { "id": 322, "level": "3", "text": "BCCat", "type": "Item", "items": null }] }] }];

document.write('<pre>' + JSON.stringify(data.reduce(flat, []), 0, 4) + '</pre>');