递归地展平对象数组

时间:2018-05-10 17:50:18

标签: javascript arrays lodash

我有以下对象数组。如何将多维对象数组展平为一维对象数组?

[{
    "name":"Locations",
    "children":[
        {
            "name":"U.S."
        },
        {
            "name":"Canada"
        },
        {
            "name":"London"
        }
    ]
},{
    "name":"Benefits",
    "children":[
        {
            "name":"U.S. Benefits",

            "children":[
                {
                    "name":"U.S. Benefits at a Glance"
                },
                {
                    "name":"U.S. Holiday Calendar"
                }
            ]
        },
        {
            "name":"London Benefits",
            "children":[
                {
                    "name":"London Benefits at a Glance"
                },
                {
                    "name":"London Holiday Calendar"
                }
            ]
        },
        {
            "name":"India Benefits",
            "children":[
                {
                    "name":"India Benefits at a Glance"
                },
                {
                    "name":"India Holiday Calendar"
                }
            ]
        }
    ]
}]

我需要所有的孩子在一维数组中与父母处于同一水平。任何帮助都将受到赞赏。

3 个答案:

答案 0 :(得分:4)

您可以在不使用reduce和传播语法的情况下执行此操作。你只需要为孩子们​​使用递归。



const data = [{"name":"Locations","children":[{"name":"U.S."},{"name":"Canada"},{"name":"London"}]},{"name":"Benefits","children":[{"name":"U.S. Benefits","children":[{"name":"U.S. Benefits at a Glance"},{"name":"U.S. Holiday Calendar"}]},{"name":"London Benefits","children":[{"name":"London Benefits at a Glance"},{"name":"London Holiday Calendar"}]},{"name":"India Benefits","children":[{"name":"India Benefits at a Glance"},{"name":"India Holiday Calendar"}]}]}]

const flatten = data => {
  return data.reduce((r, { children, ...rest}) => {
    r.push(rest);
    if (children) r.push(...flatten(children));
    return r;
  }, [])
}

console.log(flatten(data))




答案 1 :(得分:1)

您可以使用辅助函数执行递归循环并附加到运行列表。

注意:如果要删除“根”虚拟节点,只需slice(1)数组。

var flattened = flattenTree({
  "name" : "root",            // Need a root entry, because the data is an array
  "children" : getData()      // Grab the data at the bottom
}, {
  nameKey : 'name',           // The name key; configurable option
  childrenKey : 'children'    // The children key; configurable option
});

console.log(flattened);       // Flattened data printed to the console

function flattenTree(tree, options) {
  options = options || {};
  var nameKey = options.nameKey || 'name';
  var childrenKey = options.childrenKey || 'children'
  var resultList = [];
  flattenTreeRecurse(tree, resultList, nameKey, childrenKey);
  return resultList;
}

/** @private -- Recursive inner-call */
function flattenTreeRecurse(tree, list, nameKey, childrenKey) {
  var entry = {};
  entry[nameKey] = tree[nameKey];
  list.push(entry);
  if (tree[childrenKey] && tree[childrenKey].length > 0) {
    tree[childrenKey].forEach(child => flattenTreeRecurse(child, list, nameKey, childrenKey));
  }
}

function getData() {
  return [{
    "name": "Locations",
    "children": [{
      "name": "U.S."
    }, {
      "name": "Canada"
    }, {
      "name": "London"
    }]
  }, {
    "name": "Benefits",
    "children": [{
        "name": "U.S. Benefits",

        "children": [{
          "name": "U.S. Benefits at a Glance"
        }, {
          "name": "U.S. Holiday Calendar"
        }]
      },
      {
        "name": "London Benefits",
        "children": [{
          "name": "London Benefits at a Glance"
        }, {
          "name": "London Holiday Calendar"
        }]
      },
      {
        "name": "India Benefits",
        "children": [{
          "name": "India Benefits at a Glance"
        }, {
          "name": "India Holiday Calendar"
        }]
      }
    ]
  }];
}
.as-console-wrapper { top: 0; max-height: 100% !important; }

答案 2 :(得分:0)

@nenad-vracar的答案修改为可重用的样式:

const mock = [{"name":"Locations","children":[{"name":"U.S."},{"name":"Canada"},{"name":"London"}]},{"name":"Benefits","children":[{"name":"U.S. Benefits","children":[{"name":"U.S. Benefits at a Glance"},{"name":"U.S. Holiday Calendar"}]},{"name":"London Benefits","children":[{"name":"London Benefits at a Glance"},{"name":"London Holiday Calendar"}]},{"name":"India Benefits","children":[{"name":"India Benefits at a Glance"},{"name":"India Holiday Calendar"}]}]}];

const flatDeepByKey = (data, key) => {
  return data.reduce((prev, el) => {
    prev.push(el);
    if (el[key]) {
      prev.push(...flatDeepByKey(el[key], key))
    };
    return prev;
  }, [])
};

console.log(flatDeepByKey(mock, 'children'));