Deep Flatten JavaScript Object Recursively

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

Data:

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


        
相关标签:
14条回答
  • 2021-02-18 21:10

    Modified Роман Парадеев answer to make it somewhat more dynamic.

    function flatten(xs, childSelector) {
      return xs.reduce((acc, x) => {
        acc = acc.concat(x);
        let children = childSelector(x);
        if (children) {
          acc = acc.concat(flatten(children, childSelector));
        }
        return acc;
      }, []);
    }
    

    Now items is not hardcoded, and you can use it flatten(data, x => x.items).

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

    With a bit of ES6 flavor

    function flatten(xs) {
      return xs.reduce((acc, x) => {
        acc = acc.concat(x);
        if (x.items) {
          acc = acc.concat(flatten(x.items));
          x.items = [];
        }
        return acc;
      }, []);
    }
    
    0 讨论(0)
  • 2021-02-18 21:14

    Here is my version of the recursive flattenItems function. Note that I have removed the items property at all levels in the final result.

    function flattenItems(data) {
        // flat is the array that we will return by the end
        var flat = [];
        data.forEach(function(item) {
            // get child properties only
            var flatItem = {};
            Object.keys(item).forEach(function(key) {
                if(item[key] && item.hasOwnProperty(key) && !Array.isArray(item[key])) {
                    flatItem[key] = item[key];
                }
                // recursive flattern on subitems
                // add recursive call results to the 
                // current stack version of "flat", by merging arrays
                else if(Array.isArray(item[key])) {
                    Array.prototype.push.apply(flat, flattenItems(item[key]));
                }
            });
            flat.push(flatItem);
        });
        // sort by level before returning
        return flat.sort(function(i1, i2) {
            return parseInt(i1.level) - parseInt(i2.level);
        });
      }
    

    Here is a fiddle using your sample data, check the console.

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

    Using _.flatMapDeep (available since Lodash 4.7):

    var flatten = function(item) {
      return [item, _.flatMapDeep(item.items, flatten)];
    }
    
    var result = _.flatMapDeep(data, flatten);
    
    0 讨论(0)
  • 2021-02-18 21:19

    Here is solution using recursive function which I called flattenNestedObjectsArray()(for native JavaScript):

    function flattenNestedObjectsArray(arr, part){
        var flattened = part || [], items;
        arr.forEach(function(v){
            if (Array.isArray(v.items) && v.items.length) {
                items = v.items;
                v.items = [];
                flattened.push(v);
                flattened.concat(flattened, flattenNestedObjectsArray(items, flattened));                
            } else {
                flattened.push(v);
            }        
        });
        return flattened;
    }
    
    var flattened = flattenNestedObjectsArray(data);
    console.log(JSON.stringify(flattened, 0, 4));
    

    The console.log output:

    [
        {
            "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
        }
    ]
    
    0 讨论(0)
  • 2021-02-18 21:19

    another way with recursive reducer function

     _.reduce(data, function reducer(result, val) {
         var items = _.reduce(val.items, reducer, []);
         val.items = _.isArray(val.items) ? [] : val.items;
         return _.concat(result, val, items);
     }, []);
    
    0 讨论(0)
提交回复
热议问题