【问题标题】:Get value from nested arrays of objects从嵌套的对象数组中获取值
【发布时间】:2021-11-29 21:33:20
【问题描述】:

我的数据结构如下:

const arr = [{
    id: 0,
    name: 'Biomes',
    icon: 'mdi-image-filter-hdr',
    isParent: true,
    children: [{
        id: 1,
        name: 'Redwood forest',
        icon: 'mdi-image-filter-hdr'
    }]
},{
    id: 2,
    name: 'Trees',
    icon: 'mdi-pine-tree',
    children: [{
        id: 8,
        name: 'Redwood',
        icon: 'mdi-pine-tree'
    }]
}];

顶层是一个对象数组,每个对象可以有一个子字段children,它本身可以是一个对象数组。如果我知道id 的值,我如何根据该 id 值找到对象(或更重要的是对象名称)?

【问题讨论】:

  • id 会匹配父母和孩子中的对象还是只匹配父母?
  • @bassxzero 它将匹配其中一个。它可以匹配任何父对象或任何子对象。
  • 嵌套是只有一层还是可以更深?
  • 可以有多个具有相同Id的孩子?
  • 目前只有一个级别,但我更喜欢可扩展到 N 级深度的解决方案

标签: javascript vue.js ecmascript-6


【解决方案1】:

您可以在这里使用递归来获取对象,无论它有多深。我已经过滤掉了这个对象。它只会给出没有children 属性的对象。你可以按照你想要的方式包含它

function getObjectFromId(arr, id) {
  for (let i = 0; i < arr.length; ++i) {
    if (arr[i].id === id) {
     // return arr[i]   // If you want full object with children
      const { children, ...rest } = arr[i];
      return rest;
    }
    if (arr[i].children) {
      const result = getObjectFromId(arr[i].children, id);
      if (result) return result;
    }
  }
}

const arr = [
  {
    id: 0,
    name: "Biomes",
    icon: "mdi-image-filter-hdr",
    isParent: true,
    children: [
      {
        id: 1,
        name: "Redwood forest",
        icon: "mdi-image-filter-hdr",
      },
    ],
  },
  {
    id: 2,
    name: "Trees",
    icon: "mdi-pine-tree",
    children: [
      {
        id: 8,
        name: "Redwood",
        icon: "mdi-pine-tree",
        children: [
          {
            id: 9,
            name: "Redwood",
            icon: "mdi-pine-tree",
          },
        ],
      },
    ],
  },
];

function getObjectFromId(arr, id) {
  for (let i = 0; i < arr.length; ++i) {
    if (arr[i].id === id) {
      // return arr[i]   // If you want full object with children
      const { children, ...rest } = arr[i];
      return rest;
    }
    if (arr[i].children) {
      const result = getObjectFromId(arr[i].children, id);
      if (result) return result;
    }
  }
}

console.log(getObjectFromId(arr, 1));
console.log(getObjectFromId(arr, 8));
console.log(getObjectFromId(arr, 9));
/* This is not a part of answer. It is just to give the output fill height. So IGNORE IT */
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案2】:

    解决方案 1: 2 for 循环。

    const inputArray = [{
        id: 0,
        name: 'Biomes',
        icon: 'mdi-image-filter-hdr',
        isParent: true,
        children: [{
          id: 1,
          name: "Redwood forest",
          icon: 'mdi-image-filter-hdr'
        }]
      },
      {
        id: 2,
        name: 'Trees',
        icon: 'mdi-pine-tree',
        children: [{
          id: 8,
          name: "Redwood",
          icon: 'mdi-pine-tree',
        }]
      }
    ];
    
    console.log(findById(8));
    
    function findById(id) {
      for (const parent of inputArray) {
        if (parent.id === id)
          return parent;     
        for (const child of parent.children)
          if (child.id === id)
            return child;
      }
      return null;
    }

    解决方案2:多个嵌套层级:

    const inputArray = [{
        id: 0,
        name: 'Biomes',
        icon: 'mdi-image-filter-hdr',
        isParent: true,
        children: [{
          id: 1,
          name: "Redwood forest",
          icon: 'mdi-image-filter-hdr'
        }]
      },
      {
        id: 2,
        name: 'Trees',
        icon: 'mdi-pine-tree',
        children: [{
          id: 8,
          name: "Redwood",
          icon: 'mdi-pine-tree',
          children: [{
            id: 12,
            name: "Test Level 2",
            icon: 'mdi-pine-tree',
            children: [{
              id: 13,
              name: "Test Level 3",
              icon: 'mdi-pine-tree',
            }]
          }]
        }]
      }
    ];
    
    console.log(findById(13, inputArray));
    
    function findById(id, array) {
      for (const parent of array) {
        if (parent.id === id)
          return parent;
    
        if ('children' in parent) {
          const result = findById(id, parent.children);
          if (result) return result;
        }
      }
    
      return null;
    }

    【讨论】:

    • 这确实是仅用于单层嵌套的完美解决方案,但如果它更深就行不通了吗? 目前只有一个级别,但我更喜欢可扩展到 N 级深度的解决方案
    • @decpk 我添加了两种解决方案。
    【解决方案3】:

    const arr = [{
        id: 0,
        name: 'Biomes',
        icon: 'mdi-image-filter-hdr',
        isParent: true,
        children: [{
            id: 1,
            name: 'Redwood forest',
            icon: 'mdi-image-filter-hdr'
        }]
    },{
        id: 2,
        name: 'Trees',
        icon: 'mdi-pine-tree',
        children: [{
            id: 0,
            name: 'whatever',
            icon: 'new-tree'
        },{
            id: 8,
            name: 'Redwood',
            icon: 'mdi-pine-tree'
        }]
    }];
    
    const findById = (id) => arr
        .filter(x => x.id === id || x.children.some(child => id === child.id))
        .map(y => ({...y, children: y.children.filter(child => id === child.id)}))
    
    console.log(findById(0))

    你可以先filter out all parents who have the same id or if the parent has child with the same id via some,然后使用map和filter删除所有没有相同ID的孩子没有id

    【讨论】:

      【解决方案4】:

      在父子级别查找

      const arr=[{id:0,name:'Biomes',icon:'mdi-image-filter-hdr',isParent:!0,children:[{id:1,name:"Redwood forest",icon:'mdi-image-filter-hdr'}]},{id:2,name:'Trees',icon:'mdi-pine-tree',children:[{id:8,name:"Redwood",icon:'mdi-pine-tree',}]}]
      
      const res = arr.reduce((a,item)=>{
          const { children, ...i} = item; 
          a.push(...children, i);
          return a; 
      },[]);
      
      function findInData(id){
        return res.find(o=>o.id===id);
      }
      
      console.log(findInData(8)?.name);
      console.log(findInData(2)?.name);

      【讨论】:

        【解决方案5】:

        孩子的第一个参数

        main 的第二个参数

        const arr = [
            {id: 0,name: 'Biomes',icon: 'mdi-image-filter-hdr',isParent: true,
            children: [{id: 1,name: 'Redwood forest',icon: 'mdi-image-filter-hdr',},],},
            {id: 2,name: 'Trees',icon: 'mdi-pine-tree',
            children: [{id: 8,name: 'Redwood',icon: 'mdi-pine-tree',},],},
        ];
        
        const getChildById = (_id, _id2 = false)=>{
            for(const main of arr){
                if(_id2 !== false && main.id !== _id2)continue;
                for(const child of main.children){
                    if(child.id === _id)return child;
                }
            }
            return false;
        };
        
        (async()=>{
            const i_want_this_id = 8;
        
            //
        
            const a = getChildById(i_want_this_id);
            console.log('Found', a);
        })();

        【讨论】:

          【解决方案6】:

          function findChildrenById(data, cid) {
            for (let p = 0; p < data.length; p += 1) {
              if (data[p].id === cid) return data[p].name
              let res = data[p].children.find(c => c.id === cid)
              if (res) return res.name
            }
          
            return null
          }
          
          
          const arr = [{
            id: 0,
            name: 'Biomes',
            icon: 'mdi-image-filter-hdr',
            isParent: true,
            children: [{
              id: 1,
              name: 'Redwood forest',
              icon: 'mdi-image-filter-hdr'
            }]
          }, {
            id: 2,
            name: 'Trees',
            icon: 'mdi-pine-tree',
            children: [{
              id: 8,
              name: 'Redwood',
              icon: 'mdi-pine-tree'
            }]
          }];
          
          console.log(findChildrenById(arr, 2))

          【讨论】:

            【解决方案7】:

            一种方法是使用Array find() 方法

            https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

            let object= arr.find((item)=>item.id === "your ID");
            console.log(object?.name);
            

            const arr = [{
                id: 0,
                name: 'Biomes',
                icon: 'mdi-image-filter-hdr',
                isParent: true,
                children: [{
                    id: 1,
                    name: 'Redwood forest',
                    icon: 'mdi-image-filter-hdr'
                }]
            },{
                id: 2,
                name: 'Trees',
                icon: 'mdi-pine-tree',
                children: [{
                    id: 8,
                    name: 'Redwood',
                    icon: 'mdi-pine-tree'
                }]
            }];
            
            let object= arr.find((item)=>item.id === 2);
            console.log(object?.name);
            let object= arr.find((item)=>item.id === "your ID");
            console.log(object?.name);
            

            【讨论】:

              猜你喜欢
              • 2013-10-11
              • 2020-05-10
              • 1970-01-01
              • 1970-01-01
              • 2018-10-14
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-09-21
              相关资源
              最近更新 更多