使用array.map()从对象数组中查找元素

3

我有一个对象数组,想要返回所有 id 的数组。例如:

const arr = [
    {Locations:[{id:2129, Name: 'testAA'}, {id:3431, Name: 'testAB'}, {id:4373, Name: 'testAC'}]},
    {Locations:[{id:2545, Name: 'testBA'}, {id:3431, Name: 'testBB'}]}
];     

我可以为您提供以下翻译结果:[2129, 3431, 4373, 2545, 3431]

我尝试过以下方法:

arr.map((value) => {
    let newarray = [];
    return newarray += value['Locations'].map(ID => ID.id);
});

这将返回:["2129,3431,4373", "2545,3431"] 如何将这两个数组合并?
6个回答

5

考虑到您的输入和输出不是一对一的映射,这似乎不是使用.map()的好用例。相反,我建议只在内部数组上使用.map(),而在外部使用.reduce()

const arr = [{Locations:[{id:2129, Name: 'testAA'}, {id:3431, Name: 'testAB'}, {id:4373, Name: 'testAC'}]},{Locations:[{id:2545, Name: 'testBA'}, {id:3431, Name: 'testBB'}]}];     

const result = arr.reduce((acc,{Locations}) => [...acc, ...Locations.map(i=>i.id)], []);

console.log(result);

作为替代方案,您可以使用.concat()

const arr = [{Locations:[{id:2129, Name: 'testAA'}, {id:3431, Name: 'testAB'}, {id:4373, Name: 'testAC'}]},{Locations:[{id:2545, Name: 'testBA'}, {id:3431, Name: 'testBB'}]}];     

const result = arr.reduce((acc,{Locations}) => acc.concat(Locations.map(i=>i.id)), []);

console.log(result);


1
当累加器和子数组被展平,但你需要生成一个输出数组时,flatMap 是正确的工具(但如果浏览器兼容性不允许,那么 [].concat() 是一个很好的 flatMap 替代方案)。由于 ...acc,这看起来像是二次时间复杂度。 - undefined
@ggorlen 谢谢。我已经包含了一个替代方案。 - undefined
concat在每次迭代时做的事情是一样的——不幸的是,它会创建一个全新的数组。如果你必须使用reduce,很重要的一点是return a;,这样结果数组就不会被重建arr.length次。但是这样看起来非常丑陋,表明reduce(...., [])是一种反模式(应该使用map)。如果需要兼容性,可以参考Mamum的答案或者我的答案。请随意进行基准测试。 - undefined
@ggorlen 我并不反对,只是修改我的答案来模仿已经提供的其他选择没有太多意义 :) - undefined
1
绝对没错,并且这并不是一个糟糕的答案!一般来说,大部分数据都会比较小,所以我并不是要过于苛求。 - undefined

2
你可以尝试使用 Array.prototype.flatMap() 方法:

flatMap() 方法首先使用映射函数对每个元素进行映射,然后将结果平坦化为一个新数组。它与 map() 后面跟着 depth 1 的 flat() 相同,但是 flatMap() 常常非常有用,因为将两者合并为一个方法略微更有效率。

还有 Array.prototype.map() 方法:

map() 方法创建一个新数组,其中的每个元素都是调用提供的函数后原始数组中对应元素的结果。

const arr = [
    {Locations:[{id:2129, Name: 'testAA'}, {id:3431, Name: 'testAB'}, {id:4373, Name: 'testAC'}]},
    {Locations:[{id:2545, Name: 'testBA'}, {id:3431, Name: 'testBB'}]}
];
const newarray = arr.flatMap(i => i.Locations.map(j => j.id));
console.log(newarray);


只是一点注意-不太兼容各种浏览器。 - undefined

1
尝试使用。
arr.map((value) => {
    let newarray = [];
    return newarray += value['Locations'].map(ID => ID.id);
}).join(',').split(',').map((value) => parseInt(value, 10));

这里是"事件链": ["2129,3431,4373", "2545,3431"] -> "2129,3431,4373,2545,3431" -> ["2129","3431","4373","2545","3431"] -> [2129, 3431, 4373, 2545, 3431]

1
现在我看了一下,Tyler上面的答案更简洁、更好-用那个吧。 - undefined

0

Array#flatMap 是处理这种情况的正确工具,但如果浏览器兼容性不允许使用它,你可以使用 Array#concatspread syntax 进行扁平化:

const arr = [{Locations:[{id:2129, Name: 'testAA'}, {id:3431, Name: 'testAB'}, {id:4373, Name: 'testAC'}]}, {Locations:[{id:2545, Name: 'testBA'}, {id:3431, Name: 'testBB'}]}];

console.log([].concat(...arr.map(e => e.Locations.map(e => e.id))));


0

我喜欢Tyler Roppers的答案

将两个数组连接起来 https://www.w3schools.com/jsref/jsref_concat_array.asp

虽然没有测试过,但可能可以使用return newarray.concat(value['Locations'].map(ID => ID.id));

也可以运行类似这样的代码,可能会更简洁一些。

arr.map((value) => {
    let newArray = [];
    Locations.map((location) => {
        return newArray.push(location.id)
    });
    if(newArray.length) return newArray;
    return null;
}

0

那里不是两个数组,而是一个由两个连接字符串组成的数组。你根本不需要newarray[].map()会为你返回一个新的数组。

当你理解了这一点后,你可以将它与reduce()结合使用。

你想要的结果应该是这样的:

arr
    .map((value) => value['Locations']
        .map(ID => ID.id))
    .reduce((accum, arr)=>accum.concat(arr));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接