假设我在(简化的)艺术家阵列中拥有这些嵌套的专辑数组:
const api = [
{
"id": 1,
"name": "John Coltrane",
"albums": [
{ "title": "Giant Steps" },
{ "title": "A Love Supreme"},
{ "title": "Tenor Madness"}
],
"instrument": "Saxophone"
},
{
"id": 2,
"name": "Sonny Rollins",
"albums": [
{ "title": "Saxophone Colossus" },
{ "title": "The Bridge"},
{ "title": "Tenor Madness"}
],
"instrument": "Saxophone"
}
];
我想将所有相册合并到一个新数组中,没有任何重复。
这是我到目前为止所得到的:
let albums = [];
api.forEach((api) => {
Object.keys(api).forEach((prop) => {
if (prop === 'albums') {
api[prop].forEach(album => albums.includes(album.title) ? '' : albums.push(album.title));
}
});
});
我想知道是否有更好,更简单的方法来实现这一目标,并且/或者如果在包含约5000位艺术家的数据集上这样做会很慢,每个艺术家有5-20张专辑
This answer被指出给我(可能重复),它确实解决了我的部分问题(非常有趣,谢谢!),但我对如何处理这个问题更感兴趣数组的嵌套特性。
谢谢!
答案 0 :(得分:2)
我鼓励您通过函数式编程来探索lodash库来实现它。请参阅下面的代码,它是链接的,并且是声明性的,可读的,可维护的。
const ret = _(api)
.map(x=>x.albums) // extract albums properties
.flatten() // flatten array of arrays to be array
.map(x=>x.title) // extract title
.uniq() // remove duplicacy
.value(); // trigger evaluation process
console.log(ret)
答案 1 :(得分:1)
这是一个使用Set
的解决方案,只需添加一次即可轻松完成:
let albums = [...api.reduce((result, {albums}) =>
albums.reduce((result, {title}) => result.add(title), result),
new Set()
)];
const api = [
{
"id": 1,
"name": "John Coltrane",
"albums": [
{ "title": "Giant Steps" },
{ "title": "A Love Supreme"},
{ "title": "Tenor Madness"}
],
"instrument": "Saxophone"
},
{
"id": 2,
"name": "Sonny Rollins",
"albums": [
{ "title": "Saxophone Colossus" },
{ "title": "The Bridge"},
{ "title": "Tenor Madness"}
],
"instrument": "Saxophone"
}
];
let albums = [...api.reduce((result, {albums}) =>
albums.reduce((result, {title}) => result.add(title), result),
new Set()
)];
console.log(albums);
通过查看这个替代的,更少函数式编程样式的代码来理解上面的代码可能会有所帮助,但它使用相同的逻辑:
let result = new Set();
for (let row of api)
for (let album of row.albums)
result.add(album.title);
let albums = [...result];
由于此版本没有嵌套函数,因此您认为它运行得更快。但JavaScript引擎擅长优化代码,在我对FireFox和Chrome的测试中,第一个版本在大多数情况下运行速度稍快一些。
答案 2 :(得分:0)
ES2015:
const result = api
.map(({albums}) => albums)
.reduce((res, albums) => res.concat(albums), [])
.reduce((res, {title}) =>
(!res.some(saved => saved === title) && res.push(title), res), []
);