如何判断多层嵌套数组是否仅包含指定类型的子元素?
问题描述
我有如下数据结构:
const Items = [ { coolitmes: [ { coolerItems: [{ type: "dog" }, { type: "dog" }, { type: "dog" }] }, { coolerItems: [{ type: "dog" }, { type: "dog" }, { type: "dog" }] }, { coolerItems: [{ type: "cat" }, { type: "cat" }, { type: "cat" }] } ] }, { coolitmes: [ { coolerItems: [{ type: "dog" }, { type: "dog" }, { type: "dog" }] }, { coolerItems: [{ type: "dog" }, { type: "dog" }, { type: "dog" }] }, { coolerItems: [{ type: "dog" }, { type: "dog" }, { type: "dog" }] } ] }, { coolitmes: [ { coolerItems: [{ type: "dog" }, { type: "dog" }, { type: "dog" }] }, { coolerItems: [{ type: "dog" }, { type: "dog" }, { type: "dog" }] }, { coolerItems: [{ type: "dog" }, { type: "dog" }, { type: "dog" }] } ] } ];
其中包含3个type为cat的对象。我希望编写一个过滤算法,判断该数组是否仅包含指定类型(如cat)的子元素。目前我尝试了如下嵌套循环的函数,但不确定后续逻辑,还考虑通过统计不同type的数量来判断,请问该如何实现?
function isAllOfType(type: string) { for (let i = 0; i <= Items.length; i++) { for (let i2 = 0; i2 <= Items[i].coolitmes.length; i2++) { for (let i3 = 0; i3 <= Items[i].coolitmes[i2].coolerItems.length; i3++) { if (Items[i].coolitmes[i2].coolerItems[i3].type === type) { // what do I do here } } } } // return true/false depending if all chidlren are of certian type } const isAllCat = isAllOfType('cat')
解决方案
方法一:优化嵌套循环(提前终止判断)
你的嵌套循环思路可行,但存在两个问题:一是循环条件用了<=,会触发数组越界(数组索引从0开始,长度为n时最大索引是n-1);二是逻辑方向不对,应该反向判断——只要找到一个不符合指定类型的元素,直接返回false,遍历完所有元素都没问题再返回true。
修改后的代码:
function isAllOfType(type: string): boolean { // 遍历外层Items数组 for (let i = 0; i < Items.length; i++) { // 遍历每个item的coolitmes数组 for (let j = 0; j < Items[i].coolitmes.length; j++) { // 遍历每个coolitem的coolerItems数组 for (let k = 0; k < Items[i].coolitmes[j].coolerItems.length; k++) { // 发现不符合的元素直接返回false if (Items[i].coolitmes[j].coolerItems[k].type !== type) { return false; } } } } // 所有元素都符合要求,返回true return true; } const isAllCat = isAllOfType('cat'); // 返回false,因为存在大量dog类型元素
方法二:统计类型数量判断
如果需要了解具体类型分布,或者偏好函数式写法,可以先收集所有子元素的type,再做判断:
写法1:扁平化数组+全量校验
function isAllOfType(type: string): boolean { // 逐层扁平化,提取所有type值 const allTypes = Items.flatMap(item => item.coolitmes.flatMap(coolItem => coolItem.coolerItems.map(subItem => subItem.type) ) ); // 校验所有type是否等于目标类型 return allTypes.every(t => t === type); }
写法2:统计各类型数量
如果需要同时知道不同类型的具体数量,可以用对象记录:
function checkAllType(type: string): { isAll: boolean, typeCount: Record<string, number> } { const typeCount: Record<string, number> = {}; Items.forEach(item => { item.coolitmes.forEach(coolItem => { coolItem.coolerItems.forEach(subItem => { const t = subItem.type; typeCount[t] = (typeCount[t] || 0) + 1; }); }); }); // 判断是否只有目标类型存在 const isAll = Object.keys(typeCount).length === 1 && typeCount[type] !== undefined; return { isAll, typeCount }; } const result = checkAllType('cat'); console.log(result.isAll); // false console.log(result.typeCount); // { dog: 27, cat: 3 }
内容的提问来源于stack exchange,提问作者CodingLittle
相关产品推荐
相关产品推荐

