Deep Flatten JavaScript Object Recursively

后端 未结 14 2230
囚心锁ツ
囚心锁ツ 2021-02-18 20:34

Data:

var data = [
    {
      \"id\": 1,
      \"level\": \"1\",
      \"text\": \"Sammy\",
      \"type\": \"Item\",
      \"items\": [
               


        
相关标签:
14条回答
  • 2021-02-18 20:56

    Since this older question has been brought back up, here is a modern version. It does not mutate (@Nina Scholz: or mutilate!) the original data, but returns a new array containing new objects.

    const flattenItems = (xs) =>
      xs. flatMap (({items, ... node}) => [node, ... flattenItems (items || [])])
    
    const 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}]}]}]
    
    console .log (flattenItems (data))
    .as-console-wrapper {max-height: 100% !important; top: 0}

    This version does not include the fairly useless items property. It would be easy enough to add it in, with something like this:

    const flattenItems = (xs) =>
      xs. flatMap (({items, ... node}) => [
        {... node, items: items == null ? null : []}, 
        ... flattenItems (items || [])
      ])
    
    0 讨论(0)
  • 2021-02-18 21:01

    This solution should work on IE11; uses filter, map, and reduce.

    var item = function(x) {
        return {
            "id": x.id,
            "level": x.level,
            "text": x.text,
            "type": x.type,
            "items": x.items ? [] : null
        }
    }
    
    var flatten = function(a, b) {
        return a.concat(b);
    };
    
    var onlyUnique = function(acc, curr) {
        if (acc.length == 0) {
            acc.push(curr);
        } else {
            var search = acc.filter(function(x){return x.id===curr.id;})
            if (search.length == 0) {
                acc.push(curr);
            }
        }
        return acc;
    }
    
    var newData = data.map(function(x) {
    
        return x.items.map(function(xx) {
            return xx.items.map(function(xxx) {
                return [item(x), item(xx), item(xxx)];
            }).reduce(flatten, []);
    
    
        }).reduce(flatten, [])
    
    
    
    }).reduce(flatten, []).reduce(onlyUnique, []);;
    
    console.log(JSON.stringify(newData, null, 2))
    
    0 讨论(0)
  • 2021-02-18 21:02

    A shorter solution using reduce and recursion

    function flatten(data){
      return data.reduce(function(result,next){
        result.push(next);
        if(next.items){
          result = result.concat(flatten(next.items));  
          next.items = [];
        }
        return result;
      },[]);
    }
    
    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
                }
              ]
            }
          ]
        }
      ];
    
    var result = flatten(data);
    
    document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

    0 讨论(0)
  • 2021-02-18 21:06

    A solution in plain Javascript with respect to the items. It does not mutate 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>');

    0 讨论(0)
  • 2021-02-18 21:07

    Plain JavaScript

    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 }] }] }];
    
    var r = [];
    
    function flatten(a) {
        if (a.length == 0) return;
        var o = {};
        o.id = a[0].id;
        o.level = a[0].level;
        o.text = a[0].text;
        o.type = a[0].type
        o.items = a[0].items == null ? null : []
        r.push(o);
        if (Array.isArray(a[0].items)) {
            flatten(a[0].items);
        }
        a.shift();
        flatten(a);
    }
    
    flatten(data);
    
    document.write('<pre>' + JSON.stringify(r, 0, 2) + '</pre>');

    0 讨论(0)
  • 2021-02-18 21:08

    Since Lo-Dash 3.0.0, _.flattenDeep(data) will return a deeply flattened array as you desire. There is also a _.flatten(data) function that flattens shallowly.

    0 讨论(0)
提交回复
热议问题