返回 1. 使用
2. 使用
4. 先构建
JavaScript 数组比较:获取匹配 ID 对象的 Name 值
javascript
2025-03-22 19:16:34
JavaScript 中比较两个数组并从第二个数组获取匹配记录
这问题问的...比较抽象啊。简单来说,就是要根据第一个数组里的 ID,从第二个数组里找出对应 ID 的对象,然后提取出这些对象的 name
属性,组成一个新的数组。
问题原因
原代码的错误在于使用了 find
方法,而且比较的方式不对。find
方法只会返回 第一个 满足条件的元素,而且在循环里直接拿 array1
的元素跟 array2
的 id
属性比较,逻辑上就不对。 你需要遍历 array1
,然后对于每个元素,都要在 array2
里面找对应 id
的对象。
解决方案
1. 使用 filter
+ map
(推荐)
这是最简洁明了的方案,可读性高,也容易理解。
- 原理:
- 先用
filter
方法过滤array2
,找出所有id
属性存在于array1
中的对象。 - 再用
map
方法将过滤后的对象数组转换为只包含name
属性的数组。
- 先用
- 代码示例:
var array1 = [2, 10];
var array2 = [
{ id: 1, name: 'robin' },
{ id: 2, name: 'david' },
{ id: 3, name: 'john' },
{ id: 6, name: 'vinay' },
{ id: 10, name: 'ramdin' },
{ id: 15, name: 'vin' },
];
const result = array2
.filter(item => array1.includes(item.id))
.map(item => item.name);
console.log(result); // 输出: ['david', 'ramdin']
- 进阶技巧:
如果array1
很大,可以使用Set
来提高includes
的效率。
用var array1 = [2, 10]; const array1Set = new Set(array1); // 转换为 Set var array2 = [ { id: 1, name: 'robin' }, { id: 2, name: 'david' }, { id: 3, name: 'john' }, { id: 6, name: 'vinay' }, { id: 10, name: 'ramdin' }, { id: 15, name: 'vin' }, ]; const result = array2 .filter(item => array1Set.has(item.id)) // 使用 has 方法 .map(item => item.name); console.log(result);
Set
的has
方法查找比数组的includes
方法快,尤其是在数组很大的时候。
2. 使用 reduce
reduce
方法能一行代码搞定,但可读性稍微差点。
- 原理:
reduce
遍历array2
,对每个元素进行判断,如果id
在array1
中,就把name
属性添加到累加器数组里。 - 代码示例:
var array1 = [2, 10];
var array2 = [
{ id: 1, name: 'robin' },
{ id: 2, name: 'david' },
{ id: 3, name: 'john' },
{ id: 6, name: 'vinay' },
{ id: 10, name: 'ramdin' },
{ id: 15, name: 'vin' },
];
const result = array2.reduce((acc, item) => {
if (array1.includes(item.id)) {
acc.push(item.name);
}
return acc;
}, []);
console.log(result); // 输出: ['david', 'ramdin']
-
进阶技巧 : 同样,如果
array1
非常大,也可以将其转为Set
来优化includes
。var array1 = [2, 10]; const array1Set = new Set(array1); var array2 = [ { id: 1, name: 'robin' }, { id: 2, name: 'david' }, { id: 3, name: 'john' }, { id: 6, name: 'vinay' }, { id: 10, name: 'ramdin' }, { id: 15, name: 'vin' }, ]; const result = array2.reduce((acc, item) => { if (array1Set.has(item.id)) { acc.push(item.name); } return acc; }, []); console.log(result);
3. 使用双重循环 (不推荐)
双重循环虽然能解决问题,但效率最低,代码也比较啰嗦。
- 原理: 外层循环遍历
array1
,内层循环遍历array2
,逐个比较id
。 - 代码示例:
var array1 = [2, 10];
var array2 = [
{ id: 1, name: 'robin' },
{ id: 2, name: 'david' },
{ id: 3, name: 'john' },
{ id: 6, name: 'vinay' },
{ id: 10, name: 'ramdin' },
{ id: 15, name: 'vin' },
];
const result = [];
for (let i = 0; i < array1.length; i++) {
for (let j = 0; j < array2.length; j++) {
if (array1[i] === array2[j].id) {
result.push(array2[j].name);
break; // 找到了就跳出内层循环
}
}
}
console.log(result); // 输出: ['david', 'ramdin']
- 可以考虑使用
forEach
使代码稍微简洁一点。
4. 先构建array2
的Map,再查询 (处理大量数据)
-
原理: 如果
array2
非常大,或者需要进行多次这样的查询,可以先构建一个id
到name
的映射(Map),这样查询的时候就不用每次都遍历array2
了。 -
代码:
var array1 = [2, 10];
var array2 = [
{ id: 1, name: 'robin' },
{ id: 2, name: 'david' },
{ id: 3, name: 'john' },
{ id: 6, name: 'vinay' },
{ id: 10, name: 'ramdin' },
{ id: 15, name: 'vin' },
];
const idToNameMap = new Map(array2.map(item => [item.id, item.name]));
const result = array1.map(id => idToNameMap.get(id)).filter(name => name !== undefined);
console.log(result); // 输出: ['david', 'ramdin']
-
解释:
new Map(array2.map(item => [item.id, item.name]))
:把array2
转化成一个Map
,其中键(key)是id
,值(value)是name
。array1.map(id => idToNameMap.get(id))
:对array1
中的每个id
,去Map
里取对应的name
。如果id
不存在,get
方法返回undefined
。.filter(name => name !== undefined)
把上一步中产生的undefined
值过滤掉。
-
额外说明: 这种方法的优势在于,如果
array2
很大,并且你需要根据array1
里的不同 ID 值进行多次查询,那么只需要构建一次 Map,后续查询就会非常快。
总结
选择哪个方法取决于你的具体需求:
- 如果要代码简单,可读性好,就用
filter
+map
。 - 如果要追求极致简洁(但牺牲一点可读性),用
reduce
。 - 不要用双重循环,效率太低。
- 如果
array2
非常大,或者要进行多次查询,先构建 Map。
尽量避免在循环内部做复杂的操作或者使用性能较差的方法,影响网页或者服务器响应。