所以我不确定为什么我会遇到如此困难的时刻,但是我有一个id数组,我试图用它映射到对象数组上以找到相应的id,但是从另一个返回值键。
即:
arr=[13, 1, 16]
arrObj= [{
id: 1,
name: "cat"
}, {
id: 10,
name: "tiger",
}, {
id: 3,
name: "dog",
}, {
id: 16,
name: "bear",
}, {
id: 8,
name: "fish",
}, {
id: 13,
name: "goat",
}]
,我希望它返回:
["goat", "cat", "bear"]
我有一个嵌套的映射函数,可以执行此操作,但是对于没有相应ID的对象,返回未定义。我可以从返回的数组中过滤出未定义的对象,但是似乎有一种更干净/更有效的方法来实现这一点。
最干净的方法是什么?
答案 0 :(得分:5)
您可以使用Array#map
并使用Array#find
搜索相应的对象。然后以name
作为返回值。
var arr = [13, 1, 16],
arrObj = [{ id: 1, name: "cat" }, { id: 10, name: "tiger" }, { id: 3, name: "dog" }, { id: 16, name: "bear" }, { id: 8, name: "fish" }, { id: 13, name: "goat" }],
result = arr.map(id => arrObj.find(o => o.id === id).name);
console.log(result);
对于大量数据,您可以使用Map
并通过映射键值对来构建它,然后映射该映射的结果。
var arr = [13, 1, 16],
arrObj = [{ id: 1, name: "cat" }, { id: 10, name: "tiger" }, { id: 3, name: "dog" }, { id: 16, name: "bear" }, { id: 8, name: "fish" }, { id: 13, name: "goat" }],
result = arr.map(
Map.prototype.get,
new Map(arrObj.map(({ id, name }) => [id, name]))
);
console.log(result);
答案 1 :(得分:2)
尝试一下:
var arr=[13, 1, 16];
var arrObj= [{
id: 1,
name: "cat"
}, {
id: 10,
name: "tiger",
}, {
id: 3,
name: "dog",
}, {
id: 16,
name: "bear",
}, {
id: 8,
name: "fish",
}, {
id: 13,
name: "goat",
}];
var result = arr.map(id => arrObj.find(x => x.id == id)).map(x => x.name)
console.log(result);
// ["goat", "cat", "bear"]
.map()
(来自MDN网络文档):
方法使用调用提供的结果创建一个新数组 在调用数组中的每个元素上起作用。
.find()
(来自MDN网络文档):
方法返回数组中第一个元素的值 满足提供的测试功能。否则
undefined
是 返回。
答案 2 :(得分:1)
已经有了很多好的答案,但是我觉得有必要推动更新的语法,因为从长远来看,它的使用范围更大。
const getNamesBasedOnIds = (arr, listOfIds) => {
return arr.reduce(((sum, element) =>
[...sum, ...(listOfIds.includes(element.id) ? [element.name] : [])]),
[]);
}
const animals = getNamesBasedOnIds(arrObj, [13,1,16]);
使用Array.filter
,然后使用Array.map
,需要两次运行Array
最大值。
如果{{1}中存在Array.reduce
,则可以将elements
添加到sum
中,然后在运行listOfIds
之后,一旦获得结果< / p>
arrObj
的运行速度很慢,但是它更多的是用于展示矛操作符的使用情况
以上等同于
[...sum, ...(listOfIds.includes(element.id) ? [element.name] : [])]
最快的方法是使用sum.concat(listOfIds.includes(element.id) ? element.name : [])]
Array.push
答案 3 :(得分:0)
您可以先使用.filter
进行过滤,然后使用.map
输出所需的属性
此处
var arr = [13, 1, 16],
arrObj = [{
id: 1,
name: "cat"
}, {
id: 10,
name: "tiger",
}, {
id: 3,
name: "dog",
}, {
id: 16,
name: "bear",
}, {
id: 8,
name: "fish",
}, {
id: 13,
name: "goat",
}];
var res = arrObj.filter(o => arr.indexOf(o.id) >= 0);
console.log(res.map(o => o['name']))
答案 4 :(得分:0)
正确的方法是不嵌套任何循环:
思考过程
了解最大的问题是数据本身。不要让数据类型或结构不足迫使您使用错误的解决方案/代码。将数据转换为所需的数据,以便可以创建适当的解决方案。
基本上想象一下,如果 objArr 只是一个Map,您可以用来查找id的值...。那么解决方案就很简单了。因此,让我们做到这一点,然后其余的就位。数据数据是我一直说的:)
经验法则如果有帮助,请不要在循环内部运行循环。仅供参考:filter,find,map,indexOf ....都是内部循环,除非绝对必要,否则请勿嵌套它们。
该解决方案是迄今为止性能最高的。这样,您就没有运行 O(n ^ 2)(非常糟糕),而是运行了 O(n)(非常好):
const idArr = [ 13, 1, 16 ];
const objArr= [
{
id: 1,
name: "cat"
},
{
id: 10,
name: "tiger",
},
{
id: 3,
name: "dog",
},
{
id: 16,
name: "bear",
},
{
id: 8,
name: "fish",
},
{
id: 13,
name: "goat",
}
];
const idValueMap = objArr.reduce((acc, { id, name }) => ({ ...acc, [id]: name }), {});
let output = idArr.map((id) => idValueMap[id]);
console.log(output);