【问题标题】:Flatten an array with nested objects用嵌套对象展平数组
【发布时间】:2019-03-15 18:35:54
【问题描述】:

我有一个包含对象的数组,可以有子对象,子对象的结构与父对象相同,基本上只是对象嵌套。

我想知道如何使对象的结构变平,以便获得所有对象的 id,包括嵌套对象。

例如,这个结构

const data = [
  {
    id: 2,
    children: [
      {
        id: 1,
        children: []
      }
    ]
  },
  {
    id: 3,
    children: [],
  }
]

应该扁平化到这个

const data = [2,1,3]

我试过了

使用 Array.reduce() 和对象扩展语法,但我无法理解执行此操作所需的逻辑。

【问题讨论】:

    标签: javascript ecmascript-6


    【解决方案1】:

    const data = [
      {
        id: 2,
        children: [
          {
            id: 1,
            children: []
          }
        ]
      },
      {
        id: 3,
        children: [],
      }
    ]
    
    const getIds = (data) => data.map(d => [d.id, ...getIds(d.children)]).flat()
    
    console.log(getIds(data))

    【讨论】:

    • 这很优雅
    • 我已经接受了这个答案,就像单行一样!谢谢
    【解决方案2】:

    这是一个递归的工作。循环遍历数组并为其中的每个元素,将 id 推入一个新数组并为子数组重复。

    const data = [{
        id: 2,
        children: [{
          id: 1,
          children: []
        }]
      },
      {
        id: 3,
        children: [],
      }
    ];
    
    console.log(flatten(data));
    
    function flatten(data) {
      const result = [];
      recursive(data);
      return result;
    
      function recursive(data) {
        data.forEach(member => {
          result.push(member.id);
          recursive(member.children);
        });
      }
    }

    【讨论】:

      【解决方案3】:

      你可以使用JSON.stringify,并且对于id的每个键,推入一个数组:

      const data = [
        {
          id: 2,
          children: [
            {
              id: 1,
              children: []
            }
          ]
        },
        {
          id: 3,
          children: [],
        }
      ]
      const ids = [];
      JSON.stringify(data, (key, val) => {
        if (key === 'id') {
          ids.push(val);
        }
        return val;
      });
      console.log(ids);

      【讨论】:

      • 哦-酷。我不知道 stringify 带了参数。我还使用了 stringify,然后使用了正则表达式
      • 奇怪的是这不会递归:JSON.stringify(data,["id"])
      【解决方案4】:

      你可以做一些递归的方法。

      function flatArr(arr, res) {
        // iterate over the array
        arr.forEach(o => {
          // check id is present then push it into the result array
          if ('id' in o) res.push(o.id)
          // check children is present and non-empty
          // then ecursively call the function
          if (o.children && o.children.length) flatArr(o.children, res);
        })
        // return the result array(optional)
        return res;
      }
      
      console.log(flatArr(data, []));
      

      const data = [{
          id: 2,
          children: [{
            id: 1,
            children: []
          }]
        },
        {
          id: 3,
          children: [],
        }
      ];
      
      function flatArr(arr, res) {
        // iterate over the array
        arr.forEach(o => {
          // check id is present then push it into the result array
          if ('id' in o) res.push(o.id)
          // check children is present and non-empty
          // then ecursively call the function
          if (o.children && o.children.length) flatArr(o.children, res);
        })
        // return the result array(optional since it's the same array reference you are passing initially)
        return res;
      }
      
      console.log(flatArr(data, []));

      【讨论】:

        【解决方案5】:

        你可以使用递归。注意下面是arr的代码引用,所以我们可以直接push() ids给它,不需要得到return的值

        const data = [{ id: 2, children: [{ id: 1, children: [] }] }, { id: 3, children: [], } ]
        
        function getIds(data,arr){
          //iterate over array of chilren
          for(let child of data){
            //add id of each child to arr
            arr.push(child.id);
            //check if child have children add its 'ids' to same array
            if(child.children) getIds(child.children,arr);
          }
          //return array in end
          return arr;
        }
        console.log(getIds(data,[]))

        【讨论】:

          【解决方案6】:

          我不喜欢递归:)

          请注意其他 Stringify 答案 - ILST
          https://stackoverflow.com/a/55179326/295783

          const data=[{id:2,children:[{id:1,children:[]}]},{id:3,children:[],}];
          
          console.log(
            JSON.stringify(data)
              .match(/(?:"id":)(\d+)/g)
              .map(v => +v.replace(/"id":/g, ""))
          )

          但我希望有人能找到一种方法来一次性忽略非捕获组

          【讨论】:

          • 将每个值转换为Number。真的很奇怪的解决方案+1
          • @MaheerAli 完成 ;)
          【解决方案7】:

          您可以通过使用实际 id 来减少对象数组并获取它们的子对象。

          const
              getId = array => array.reduce(
                  (r, { id, children }) => [...r, id, ...getId(children)],
                  []
              ),
              data = [{ id: 2, children: [{ id: 1, children: [] }] }, { id: 3, children: [] }],
              ids = getId(data);
              
          console.log(ids);

          【讨论】:

            【解决方案8】:

            您可以使用递归方法,对每个children 进行迭代,并将所有id 推送到一个数组中。

            const data = [{ id: 2, children: [{ id: 1, children: [] }] }, { id: 3, children: [], } ],
                  getId = (data) => data.reduce((r,{id, children}) => r.concat(id, getId(children)),[]);
            console.log(getId(data));

            【讨论】:

              【解决方案9】:

              另一个版本。不是最漂亮的,但可以完成工作:

              const data = [
                  {
                      id: 2,
                      children: [
                          {
                              id: 1,
                              children: []
                          }
                      ]
                  },
                  {
                      id: 3,
                      children: [],
                  }
              ];
                  
              let mappedArray = data.map(num => [].concat(num.children.map(child => child.id)).concat(num.id));
                  mappedArray = [].concat.apply([], mappedArray);
              
              console.log(mappedArray);

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2021-03-22
                • 1970-01-01
                • 1970-01-01
                • 2021-05-14
                • 2016-05-18
                • 2013-11-06
                • 1970-01-01
                • 2018-10-24
                相关资源
                最近更新 更多