嵌套数组的遍历

1,描述:有一个类似这样结构的数组:
clipboard.png

2,需求:现在想过滤这个数组,只剩下name含有xxx的一个数组,无论是不是新数组都可以。也就是说,只对最里层的bbb这个数组进行过滤,留下name为xxx的,其它的去掉,bbb外层的都不动。
例如我现在需要这样过滤:只要name中含有 “1”的。那么结果应该是:

clipboard.png

也就是说只对 bbb 这个数组进行过滤,bbb中,符合要求(比如name属性含有“1”)的元素留下,不然就移除。如果bbb数组里的所有元素都不符合,即过滤后bbb为空数组,那么bbb,aaa组成的整个对象都不留下
不知道这样解释说清楚了没有。
3,说明:用过map加filter加indexof,没有搞出来。也用过双for循环,也没有搞出来。可能是思路受阻了,现在脑子一片浆糊。
4,伪代码即可,各路大神求助!
5,感谢各位大神的指教!

阅读 11.5k
4 个回答
var array;
var str = 'xxx';

For object in array
    object.bbb = object.bbb.filter(x => x.name.indexOf(str) !== -1)

result = array.filter(object => object.bbb.length != 0);
//test 数据
var a = [
    {
    aaa: '1',
    bbb: [
        {name: 'b1'},
        {name: 'b2'}
    ]
},
    {
        aaa: '2',
        bbb: [
            {name: 'bb2'},
            {name: 'bb3'}

        ]
    },
    {
        aaa: '3',
        bbb: [
            {name: 'bbb2'},
            {name: 'bbb3'}

        ]
    }
];

function getNames(a,i) {
    if(i==a.length-1){
        return a[i].bbb;
    }
    return a[i].bbb.concat(getNames(a,i+1));
}
console.log(getNames(a,0));  //输出如下:

[
 { name: 'b1' },
  { name: 'b2' },
  { name: 'bb2' },
  { name: 'bb3' },
  { name: 'bbb2' },
  { name: 'bbb3' } 
]

写了个通用版的

function isPlainObj(obj) {
    return Object.prototype.toString.call(obj) === '[object Object]';
}

function canTravers(obj) {
    return isPlainObj(obj) || Array.isArray(obj)
}

function solve(obj, key) {
    const res = []

    if (isPlainObj(obj)) {
        const temp = []
        for (let [_key, value] of Object.entries(obj)) {        
            if (_key === key) {
                res.push(value)
            }
            if (_key !== key && canTravers(value)) {
                temp.push(value)
            }
        }
        temp.length && [].push.apply(res, solve(temp, key))
    } else {
        for (let i = 0; i<obj.length; i++) {
            if (canTravers(obj[i])) {
                [].push.apply(res, solve(obj[i], key));
            }
        }
    }
    return res
}

function getKeyFromArr(arr, key) {
    const res = arr.reduce((acc, cur) => {
        let val;
        (canTravers(cur)) && (val = solve(cur, key))
        val && [].push.apply(acc, val)
        return acc
    }, [])
    return res
}

const arr = [
    {
    aaa: '1',
    bbb: [
        {name: 'b1'},
        {name: 'b2'}
    ]
},
    {
        aaa: '2',
        bbb: [
            {name: 'bb2'},
            {name: 'bb3'}

        ]
    },
    {
        aaa: '3',
        bbb: [
            {name: 'bbb2'},
            {name: 'bbb3'}

        ]
    }
];

console.log(getKeyFromArr(arr, 'name'))

getKeyFromArr接收2个参数,待查询的数组和属性名,它遍历数组,并且使用solve函数调用类型为ObjectArray 的值,对于返回的值,塞到数组里。
solve函数,就是不断地递归,直至取到要求的key或无法继续递归为止

list.reduce((acc, ele) => acc.concat(ele.bbb), [])
    .filter(ele => ele.name.includes("xxx"));
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题