代码之家  ›  专栏  ›  技术社区  ›  koryakinp

展平javascript对象数组

  •  4
  • koryakinp  · 技术社区  · 8 年前

    我有一个层次结构的对象数组,如下所示:

    [
        {name: 'ParentOne', children: [
            {name: 'ParentOneChildOne'},
            {name: 'ParentOneChildTwo', children: [
                {name: 'ParentOneChildTwoGrandChildOne'},
            ]},
        ]}, 
        {name: 'ParentTwo', children: [
            {name: 'ParentTwoChildOne', children: [
               {name: 'ParentTwoChildOneGrandChildOne'},
               {name: 'ParentTwoChildOneGrandChildTwo'}
            ]},
            {name: 'ParentTwoChildTwo'}
        ]}
    ];
    

    [
        {name: 'ParentOne'},
        {name: 'ParentOneChildOne'},
        {name: 'ParentOneChildTwo'},
        {name: 'ParentOneChildTwoGrandChildOne'},
        {name: 'ParentTwo'},
        {name: 'ParentTwoChildOne'},
        {name: 'ParentTwoChildOneGrandChildOne'},
        {name: 'ParentTwoChildOneGrandChildTwo'},
        {name: 'ParentTwoChildTwo'}
    ]
    

    我试过了 _.flatten() _.flatMap() ,但它不能生产我需要的东西。最好的方法是什么 .

    5 回复  |  直到 8 年前
        1
  •  14
  •   ideaboxer    8 年前

    不需要下划线/lodash。

    const arr = [
        {name: 'ParentOne', children: [
            {name: 'ParentOneChildOne'},
            {name: 'ParentOneChildTwo', children: [
                {name: 'ParentOneChildTwoGrandChildOne'},
            ]},
        ]}, 
        {name: 'ParentTwo', children: [
            {name: 'ParentTwoChildOne', children: [
               {name: 'ParentTwoChildOneGrandChildOne'},
               {name: 'ParentTwoChildOneGrandChildTwo'}
            ]},
            {name: 'ParentTwoChildTwo'}
        ]}
    ];
    
    function flatten(arr) {
        return arr? arr.reduce((result, item) => [
            ...result,
            { name: item.name },
            ...flatten(item.children)
        ], []) : [];
    }
    
    console.log(flatten(arr));
        2
  •  2
  •   adeneo    8 年前

    带有一些ES2015和LoDash/下划线

    var arr = [{
      name: 'ParentOne',
      children: [{
        name: 'ParentOneChildOne'
      }, {
        name: 'ParentOneChildTwo',
        children: [{
          name: 'ParentOneChildTwoGrandChildOne'
        }, ]
      }, ]
    }, {
      name: 'ParentTwo',
      children: [{
        name: 'ParentTwoChildOne',
        children: [{
          name: 'ParentTwoChildOneGrandChildOne'
        }, {
          name: 'ParentTwoChildOneGrandChildTwo'
        }]
      }, {
        name: 'ParentTwoChildTwo'
      }]
    }];
    
    var res = _.reduce(arr, (a, b) => {
      (rec = item => {
        _.each(item, (v, k) => (_.isObject(v) ? rec(v) : a.push(_.zipObject([k], [v]))))
      })(b);
      return a;
    }, []);
    
    console.log(res);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
        3
  •  1
  •   Nicholas Tower    8 年前

    我会使用 .reduce 递归来实现这一点。这是我使用数组的实现。reduce,但可以使用下划线的reduce函数执行相同的操作。

    const arr = [
        {name: 'ParentOne', children: [
            {name: 'ParentOneChildOne'},
            {name: 'ParentOneChildTwo', children: [
                {name: 'ParentOneChildTwoGrandChildOne'},
            ]},
        ]}, 
        {name: 'ParentTwo', children: [
            {name: 'ParentTwoChildOne', children: [
               {name: 'ParentTwoChildOneGrandChildOne'},
               {name: 'ParentTwoChildOneGrandChildTwo'}
            ]},
            {name: 'ParentTwoChildTwo'}
        ]}
    ];
    
    function flatten(arr) {
       return arr.reduce((result, current) => {
          if (current.children) {
             const children = flatten(current.children);
             delete current.children;
             result.push(current);
             result.push(...children);
          } else {
             result.push(current);
          }
          return result;
       }, [])
    }
    
    console.log(flatten(arr));
        4
  •  0
  •   Sam Conran    8 年前

    flatten 中给出的函数 this answer ,并稍微扭曲对象结构的逻辑。

    //Your object
    var data = [{
        name: 'ParentOne',
        children: [{
            name: 'ParentOneChildOne'
          },
          {
            name: 'ParentOneChildTwo',
            children: [{
              name: 'ParentOneChildTwoGrandChildOne'
            }, ]
          },
        ]
      },
      {
        name: 'ParentTwo',
        children: [{
            name: 'ParentTwoChildOne',
            children: [{
                name: 'ParentTwoChildOneGrandChildOne'
              },
              {
                name: 'ParentTwoChildOneGrandChildTwo'
              }
            ]
          },
          {
            name: 'ParentTwoChildTwo'
          }
        ]
      }
    ];
    
    //georg's flatten function
    flatten = function(x, result, prefix) {
      if (_.isObject(x)) {
        _.each(x, function(v, k) {
          flatten(v, result, prefix ? prefix + '_' + k : k)
        })
      } else {
        result[prefix] = x
      }
      return result
    }
    
    //using the function on your data
    result = flatten(data, {});
    console.log(result);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

    这有帮助吗?

        5
  •  0
  •   Nina Scholz    7 年前

    您可以使用一些销毁并使用递归函数来收集所有需要的项目。

    var array = [{ name: 'ParentOne', children: [{ name: 'ParentOneChildOne' }, { name: 'ParentOneChildTwo', children: [{ name: 'ParentOneChildTwoGrandChildOne' },] },] }, { name: 'ParentTwo', children: [{ name: 'ParentTwoChildOne', children: [{ name: 'ParentTwoChildOneGrandChildOne' }, { name: 'ParentTwoChildOneGrandChildTwo' }] }, { name: 'ParentTwoChildTwo' }] }],
        flat = (r, { name, children = [] }) => [...r, { name }, ...children.reduce(flat, []) ],
        result = array.reduce(flat, []);
        
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    在EDGE上,您需要使用不同的默认值。

    var array = [{ name: 'ParentOne', children: [{ name: 'ParentOneChildOne' }, { name: 'ParentOneChildTwo', children: [{ name: 'ParentOneChildTwoGrandChildOne' },] },] }, { name: 'ParentTwo', children: [{ name: 'ParentTwoChildOne', children: [{ name: 'ParentTwoChildOneGrandChildOne' }, { name: 'ParentTwoChildOneGrandChildTwo' }] }, { name: 'ParentTwoChildTwo' }] }],
        flat = (r, { name, children }) => [...r, { name }, ...(children || []).reduce(flat, []) ],
        result = array.reduce(flat, []);
        
    console.log(result);