我有一个小问题,就是在确定转换数组的最佳方法方面有些困难。我有一个像这样的对象数组:
[{
genre: 'fiction',
books: ['book1', 'book2'],
},
{
genre: 'fiction',
books: ['book6', 'book51'],
},
{
genre: 'non-fiction',
books: ['book23', 'book34'],
},
{
genre: 'fantasy',
books: ['book241', 'book49'],
},
{
genre: 'thriller',
books: ['book67', 'book32'],
},
{
genre: 'fantasy',
books: ['book21', 'book99'],
}];
使用香草JS,如何最好地返回一个新数组,该数组具有按“ genre”属性分组的项目,因此得到以下结果:
[{
genre: 'fiction',
books: ['book1', 'book2', 'book6', 'book51'],
},
{
genre: 'non-fiction',
books: ['book23', 'book34'],
},
{
genre: 'fantasy',
books: ['book241', 'book49', 'book21', 'book99'],
},
{
genre: 'thriller',
books: ['book67', 'book32'],
}];
我一直在各种for循环中处理这个问题,但是我还不太想出一个好的解决方案。
答案 0 :(得分:1)
这不是通用的,但可以使用:
var originalList = [{
genre: 'fiction',
books: ['book1', 'book2'],
},
{
genre: 'fiction',
books: ['book6', 'book51'],
},
{
genre: 'non-fiction',
books: ['book23', 'book34'],
},
{
genre: 'fantasy',
books: ['book241', 'book49'],
},
{
genre: 'thriller',
books: ['book67', 'book32'],
},
{
genre: 'fantasy',
books: ['book21', 'book99'],
}];
var newList = originalList.reduce((acc, val) => {
let item = acc.find(i => i.genre === val.genre); // check if the genre is in the list
if (item) {
item.books = item.books.concat(val.books); // if so add the books and move on
return acc;
}
val.books = val.books.slice(); // avoid mutation
return acc.concat([Object.assign({}, val)]); // otherwise add the current item to the list and avoid mutation
},[]);
console.log(newList);
答案 1 :(得分:1)
var originalArray = [{
genre: 'fiction',
books: ['book1', 'book2'],
},
{
genre: 'fiction',
books: ['book6', 'book51'],
},
{
genre: 'non-fiction',
books: ['book23', 'book34'],
},
{
genre: 'fantasy',
books: ['book241', 'book49'],
},
{
genre: 'thriller',
books: ['book67', 'book32'],
},
{
genre: 'fantasy',
books: ['book21', 'book99'],
}];
var newArray = [];
for(var i = 0; i< originalArray.length; i++){
var idx = newArray.findIndex(x => x.genre === originalArray[i].genre);
if(idx < 0){
newArray.push(originalArray[i]);
} else {
var newBooks = newArray[idx].books.concat(originalArray[i].books);
newArray[idx].books = newBooks;
}
}
console.log(newArray);
答案 2 :(得分:1)
一行代码答案:
const input = [{
genre: 'fiction',
books: ['book1', 'book2'],
},
{
genre: 'fiction',
books: ['book6', 'book51'],
},
{
genre: 'non-fiction',
books: ['book23', 'book34'],
},
{
genre: 'fantasy',
books: ['book241', 'book49'],
},
{
genre: 'thriller',
books: ['book67', 'book32'],
},
{
genre: 'fantasy',
books: ['book21', 'book99'],
}
]
// the code
const output = Object.entries(input.reduce((a, {genre, books}) => (a[genre] = (a[genre] || []).concat(books), a), {})).map(([genre, books]) => ({genre, books}));
// end of code
console.log(output);
答案 3 :(得分:1)
您可以利用Array.prototype.reduce
来创建一个地图,其中类型是关键,而书本则是价值。然后,您可以遍历条目并将结果映射到带有对象元素的新数组:
const arr = [{
genre: 'fiction',
books: ['book1', 'book2'],
},
{
genre: 'fiction',
books: ['book6', 'book51'],
},
{
genre: 'non-fiction',
books: ['book23', 'book34'],
},
{
genre: 'fantasy',
books: ['book241', 'book49'],
},
{
genre: 'thriller',
books: ['book67', 'book32'],
},
{
genre: 'fantasy',
books: ['book21', 'book99'],
}
];
const agg = Object.entries(arr.reduce((accum, el) => {
accum[el.genre] = accum[el.genre] ? [...accum[el.genre], ...el.books] : [...el.books]
return accum;
}, {})).map(entry => {
const [genre, books] = entry;
return {
[genre]: books
};
})
console.log(agg);
答案 4 :(得分:1)
如果要对它们进行分组,则以下代码应该起作用:
var json = [{
genre: 'fiction',
books: ['book1', 'book2'],
},
{
genre: 'fiction',
books: ['book6', 'book51'],
},
{
genre: 'non-fiction',
books: ['book23', 'book34'],
},
{
genre: 'fantasy',
books: ['book241', 'book49'],
},
{
genre: 'thriller',
books: ['book67', 'book32'],
},
{
genre: 'fantasy',
books: ['book21', 'book99'],
}];
function groupGenres(arrayOfObjects){
var genres = [], g;
arrayOfObjects.forEach(function(j){
g = false;
genres.forEach(function(o, i){
if(o.genre === j.genre)g = i;
});
if(g === false){
genres.push(j);
}
else{
genres[g].books = genres[g].books.concat(j.books);
}
});
return genres;
}
var group = groupGenres(json);
console.log(group);
答案 5 :(得分:0)
如果我们想保留对数组空间本身的更改,则可以进行排序和迭代。
function merge(A, prop, group){
A.sort((a, b) => a[prop] > b[prop] ? 1 : -1)
let key = A[0][prop]
let pointer = 1
for (let i=1; i<A.length; i++){
if (A[i][prop] != key){
A[++pointer - 1] = A[i]
key = A[i][prop]
} else {
A[pointer - 1][group].push(...A[i][group])
}
}
A.length = pointer
return A
}
var A = [{genre: 'fiction', books: ['book1', 'book2']}, {genre: 'fiction', books: ['book6', 'book51']}, {genre: 'non-fiction', books: ['book23', 'book34']}, {genre: 'fantasy', books: ['book241', 'book49']}, {genre: 'thriller', books: ['book67', 'book32']}, {genre: 'fantasy', books: ['book21', 'book99']}]
merge(A, 'genre', 'books')
console.log(JSON.stringify(A))