js两个数组的数据处理
数组一:
arr1 = [ {uid: 2},
{uid: 3},
{uid: 4}
]
数组二:
arr2 = [ {
text: '随便1',
children: [
{uid: 1},
{uid: 2}
]
},
{
text: '随便2',
children: [
{uid: 3},
{uid: 4}
]
},
{
text: '随便3',
children: [
{uid: 5},
{uid: 6}
]
}
]
想得到的效果
arr2 = [ {
text: '随便1',
children: [
{uid: 1, checked: false},
{uid: 2, checked: true}
]
},
{
text: '随便2',
children: [
{uid: 3, checked: true},
{uid: 4, checked: true}
]
},
{
text: '随便3',
children: [
{uid: 5, checked: false},
{uid: 6, checked: false}
]
}
]
数组arr1 中的uid的值对应在数组arr2 中添加属性 checked: true, 反之就是false。
请大神们帮我看看这个问题... 万分感谢。
回答:
const arr1 = [ { uid: 2 },
{ uid: 3 },
{ uid: 4 }
];
const arr2 = [
{
text: '随便1',
children: [
{ uid: 1 },
{ uid: 2 }
]
},
{
text: '随便2',
children: [
{ uid: 3 },
{ uid: 4 }
]
},
{
text: '随便3',
children: [
{ uid: 5 },
{ uid: 6 }
]
}
];
arr2.forEach(value => {
value.children.forEach(children => {
children.checked = arr1.map(a => a.uid).includes(children.uid);
});
});
console.log(arr2);
回答:
@边城 的答案提到深拷贝麻烦,其他答案目前也没有深拷贝的写法,我写一个作为补充,好像也不是很麻烦,语义也很清晰:
arr2 .map((item) => ({
...item,
children: item.children
.map((child) => ({
...child,
checked: arr1.some(({uid}) => uid === child.uid),
})),
}));
主要是使用扩展运算符(...) 和 Array.prototype.map
。这两者都只是浅拷贝,但 arr2
只有 4 层,要操作的数据正好在最深层,所以这两者正好用 4 次完成深拷贝。
map
单独换了一行,这样应该更能体现嵌套关系。
回答:
arr2.forEach((item, index) => { const uid = arr1[index].uid
item.children.forEach(i => {
if (i.uid === uid) {
i.checked = true
} else {
i.checked = false
}
})
})
回答:
分析
首先,这个真不需要用递归,因为不存在多级相同结构数据的情况。
说起来,其实就是遍历所有 children
项,然后去 arr1
里查 uid
,根据查询结果添加 checked
属性。
所以可以预见是两层循环,第一层遍历 arr2
的所有元素,第二层对每个元素遍历其 children
。
接下来要解决怎么查询的问题。遍历 children
的时候,每个 child
的 uid
是拿得到的,这个就是要查询的值。
而要在 arr1
里去查询,无非几种办法:
遍历法,可以用
Array
上定义的几个方法:some()
、find()/findIndex()
、includes()
等,// 假设用 childUid 来表示要查找的 uid
arr1.some(it => it.uid === childUid);
arr1.find(it => it.uid === childUid);
arr1.findIndex(it => it.uid === childUid) >= 0;
// 只有 includes 麻烦一点,因为要判断的东西必须是一个可以比较的值,而 {uid:1} === {uid:1} 会得到 false
arr1.map(({uid}) => uid).includes(childUid);
当然,有兴趣还可以自己写 `for` 或者 `for ... in`/ `for ... of` 循环来查找,方法多的是。
- 查表法。当然是先把
arr1
变成一个表。因为只需要判断在/不在,所以不需要用Map
,用Set
就好。注意Set
对象只需要生成一次,然后在每个循环体里使用就成。下面的示例代码是使用查表法写的,所以不单独写代码示例。
示例代码
const r = (() => { const checkIds = new Set(arr1.map(it => it.uid));
arr2.forEach(({ children = [] }) => {
children.forEach(child => child.checked = checkIds.has(child.uid));
});
return arr2;
})();
有几点需要注意:
- 封 IIFE 主要是为了
checkIds
用后即毁,不污染环境 - 是直接在在
arr2
原数据上修改的,而不是产生的新对像(深拷贝麻烦,如果不是一定要保留的数组干净,就不考虑深拷贝了)
回答:
简单来说使用了递归
arr1 = [ {uid: 2},
{uid: 3},
{uid: 4}
];
arr2 = [
{
text: '随便1',
children: [
{uid: 1},
{uid: 2}
]
},
{
text: '随便2',
children: [
{uid: 3},
{uid: 4}
]
},
{
text: '随便3',
children: [
{uid: 5},
{uid: 6}
]
}
];
var setTreeCheck =(arr,checks)=>arr.map(item=>(item.uid && (item.checked=Boolean(checks.find(check=>item.uid == check.uid))),setTreeCheck(item.children || [],checks),item));
setTreeCheck(arr2,arr1)
结果
[ {
"text": "随便1",
"children": [
{
"uid": 1,
"checked": false
},
{
"uid": 2,
"checked": true
}
]
},
{
"text": "随便2",
"children": [
{
"uid": 3,
"checked": true
},
{
"uid": 4,
"checked": true
}
]
},
{
"text": "随便3",
"children": [
{
"uid": 5,
"checked": false
},
{
"uid": 6,
"checked": false
}
]
}
]
回答:
我个人还是喜欢用最纯粹的方法来解各种算法问题,虽然用数组方法会更方便,但这有利于对解题思路和逻辑的理解,无论是map、forEach或是some,底层都离不开一层循环,归根结底还是要遍历数组,然后判断uid的值是否存在于另一个数组中,再把checked值添加进对象。
var tmp = [];for (var i = arr1.length; i--; tmp.unshift(arr1[i].uid));
for (var i = 0; i < arr2.length; ++i) {
for (var j = 0; j < arr2[i].children.length; ++j) {
var child = arr2[i].children[j];
child.checked = tmp.indexOf(child.uid) >= 0
}
}
console.dir(arr2);
回答:
let uids = arr1.map(item => { return item.uid
})
arr2.forEach(item => {
item.children.forEach(childitem => {
Object.assign(childitem, {
checked: uids.includes(childitem.uid)
})
})
})
console.log(arr2)
以上是 js两个数组的数据处理 的全部内容, 来源链接: utcz.com/p/935778.html