从包含对象数组的子项中找到值,该数组来自对象数组。

3

我有一个对象数组,包含来自对象数组的子项,我需要在父级数组中查找值,或者在此数组的子项中查找值等。可能需要使用递归算法实现。我尝试了以下代码:

var array = [
  {
    id: 1,
    value: 'value',
    children: null
  },
  {
    id: 2,
    value: 'my value',
    children: [
      {
        id: 'child1',
        value: 'my value',
        children: null
      },
      {
        id: 'child2',
        value: 'value',
        children: null
      },
      {
        id: 'child3',
        value: 'value,
        children: [
          {
            id: 'childchild1',
            value: 'my value',
            children: null
          }
        ]
      }
    ]
  },
  {
    id: 3,
    value: 'value',
    children: null
  },
  {
    id: 4,
    value: 'my value',
    children: null
  }
]


function find(searchData, target){
  return target.filter((f)=>{
    if(f.value.includes(searchData)){
      return true
    }
    if(f.children){
      return find(searchData, f.children)
    }
  })
}

find('my', array)

它返回源数组,但我需要包含文本“my”的数组


@CertainPerformance 是的,但不包括儿童。 - Marty
请包括您所给出示例的期望输出。 - trincot
3个回答

3

因为您有一个嵌套结构,所以不能使用.filter来获取所有嵌套对象 - .filter只会返回顶层匹配的对象。相反,在初始调用时定义一个空数组,然后在项目通过测试时将其推入该数组,并将该数组传递到每个递归调用中。最后,返回该数组:

var array=[{id:1,value:'value',children:null},{id:2,value:'my value',children:[{id:'child1',value:'my value',children:null},{id:'child2',value:'value',children:null},{id:'child3',value:'value',children:[{id:'childchild1',value:'my value',children:null}]}]},{id:3,value:'value',children:null},{id:4,value:'my value'}];

function find(searchData, target, accum=[]){
  target.forEach((f)=>{
    if(f.children){
      find(searchData, f.children, accum)
    }
    if(f.value.includes(searchData)){
      accum.push(f);
    }
  });
  return accum;
}

console.log(find('my', array));

(结果可能更容易通过浏览器控制台而不是堆栈片段控制台进行查看)

3
这是一个函数式编程风格的实现。为了简化输出,我只收集了匹配项的“id”值。如果您想要整个对象,请将“obj.id”替换为“obj”:

const array = [{id: 1,value: 'value',children: null},{id: 2,value: 'my value',children: [{id: 'child1',value: 'my value',children: null},{id: 'child2',value: 'value',children: null},{id: 'child3',value: 'value' ,children: [{id: 'childchild1',value: 'my value',children: null}]}]},{id: 3,value: 'value',children: null},{id: 4,value: 'my value'}];

const find = (searchData, target) => (target || []).reduce(
        (acc, obj) => acc.concat(obj.value.includes(searchData) ? obj.id : [],
                                 find(searchData, obj.children)),
        []
    );

const result = find('my', array);
console.log(result);


哇,这是非常好的、简短的代码。我需要更多的练习。 - Marty

1

有点晚了,这里是另一个递归查找:

var array = [
  {
    id: 1,
    value: 'value',
    children: null,
  },
  {
    id: 2,
    value: 'my value',
    children: [
      {
        id: 'child1',
        value: 'my value',
        children: null,
      },
      {
        id: 'child2',
        value: 'value',
        children: null,
      },
      {
        id: 'child3',
        value: 'value',
        children: [
          {
            id: 'childchild1',
            value: 'my value',
            children: null,
          },
        ],
      },
    ],
  },
  {
    id: 3,
    value: 'value',
    children: null,
  },
  {
    id: 4,
    value: 'my value',
  },
];

function find(search, arr) {
  function recur(result, search, arr) {
    if (!(arr && arr.length)) {
      return result;
    }
    return result
      .concat(
        ...arr.filter((item) =>
          item.value.includes(search),
        ),
      )
      .concat(
        ...arr.map((item) =>
          recur([], search, item.children),
        ),
      );
  }
  return recur([], search, arr);
}
console.log(find('my', array));


这是一个不错的解决方案,但是代码变长了。无论如何,还是谢谢您 :) - Marty

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接