我有一个看起来像这样的Javascript对象:
const obj = [
{
name: "Ali",
userID: 123,
type: "photo",
photo: {
"title": "Me",
"src": "/cool.jpg",
}
},
{
name: "Ali",
userID: 123,
type: "photo",
photo: {
"title": "Photo",
"src": "/photo.jpg"
}
},
{
name: "John",
userID: 1234,
type: "photo",
photo: {
"title": "Photo",
"src": "/photo.jpg"
}
},
{
name: "John",
userID: 1234,
type: "photo",
photo: {
"title": "Photo",
"src": "/photo.jpg"
}
}];
我需要遍历它并返回一个看起来像这样的数组:
const obj = [
{
name: "Ali",
userID: 123,
type: "photo",
photos: [
{
title: "Me",
src: "/cool.jpg"
},
{
title: "Photo",
src: "/photo.jpg"
}
]
},
{
name: "John",
userID: 1234,
type: "photo",
photos: [
{
"title": "Me",
"src": "photo.jpg"
},
{
title: "Photo",
src: "/photo.jpg"
}
]
}
]
请注意,第一个对象可以包含一个具有相同名称的对象超过100次,我只需要它一次并且在他所有照片的数组中。我该怎么做?我应该使用什么类型的循环?感谢...
答案 0 :(得分:2)
这是另一个ES6脚本:
function merge(input) {
return [...input.reduce( (acc, {name, userID, type, photo} ) => {
let obj = acc.get(name) || {name, userID, type, photos: []};
obj.photos.push(photo);
return acc.set(name, obj);
}, new Map()).values()];
}
// Sample data
var input = [{
name: "Ali",
userID: 123,
type: "photo",
photo: {
"title": "Me",
"src": "/cool.jpg",
}
},
{
name: "Ali",
userID: 123,
type: "photo",
photo: {
"title": "Photo",
"src": "/photo.jpg"
}
},
{
name: "John",
userID: 1234,
type: "photo",
photo: {
"title": "Photo",
"src": "/photo.jpg"
}
},
{
name: "John",
userID: 1234,
type: "photo",
photo: {
"title": "Photo",
"src": "/photo.jpg"
}
}];
// convert
result = merge(input);
// output result
console.log(result);
input.reduce
迭代输入,并累积一个初始化为新Map的值(reduce
的第二个参数)。
在每次迭代中,累计值作为第一个参数传递,第二个参数接收输入元素。通过destructuring assignment,我们为每个name
,userID
,type
和photo
属性获取变量。
每次迭代都会执行三个语句:
obj
被定义为我们对name
值的累积对象,或者(||
)如果我们还没有,作为给定的输入元素,但是没有photo
属性且使用新的photos
数组:{name, userID, type, photos: []}
。
将当前照片添加到其中。
将生成的对象分配回累积的Map对象,该对象本身将返回到reduce
内部。它将作为下一次迭代的第一个参数传递,等等。
reduce
返回最终累积的对象,即Map。由于这不是所需的输出格式,因此将其转换为数组,通过取values
(我们不再需要键),并将其转换为{{3 ([... ]
)。
答案 1 :(得分:1)
这可以满足您的大部分需求:
var sorted = {};
obj.forEach(function(element){
if(sorted[element.name]){
sorted[element.name].photos.push(element.photo)
}else{
sorted[element.name] = {
name: element.name,
userID: element.userID,
type: element.type,
photos:[element.photo]
}
}
});
这不会创建一个数组,它会创建一个名称为键的对象。
const obj = [
{
name: "Ali",
userID: 123,
type: "photo",
photo: {
"title": "Me",
"src": "/cool.jpg",
}
},
{
name: "Ali",
userID: 123,
type: "photo",
photo: {
"title": "Photo",
"src": "/photo.jpg"
}
},
{
name: "John",
userID: 1234,
type: "photo",
photo: {
"title": "Photo",
"src": "/photo.jpg"
}
},
{
name: "John",
userID: 1234,
type: "photo",
photo: {
"title": "Photo",
"src": "/photo.jpg"
}
}];
var sorted = {};
obj.forEach(function(element){
if(sorted[element.name]){
sorted[element.name].photos.push(element.photo)
}else{
sorted[element.name] = {
name: element.name,
userID: element.userID,
type: element.type,
photos:[element.photo]
}
}
console.log(sorted);
});
var sortedarray = sorted.map()
console.log(sortedarray);
您可以添加此代码以将对象转换为数组:
var sortedarray = Object.keys(sorted).map(function(person){
return sorted[person]});
答案 2 :(得分:1)
使用ES6并使用数据副本创建新对象,从而保留原始数据。
function merge(obj) {
const temp = new Map();
for (let r of obj) {
if (temp.has(r.userID)) {
temp.get(r.userID).photos.push(Object.assign({}, r.photo));
} else {
const entry = Object.assign({}, r);
entry.photos = [Object.assign({}, r.photo)];
delete entry.photo;
temp.set(r.userID, entry);
}
}
return Array.from(temp, x => x[1]);
}
const obj = [{
name: "Ali",
userID: 123,
type: "photo",
photo: {
"title": "Me",
"src": "/cool.jpg",
}
}, {
name: "Ali",
userID: 123,
type: "photo",
photo: {
"title": "Photo",
"src": "/photo.jpg"
}
}, {
name: "John",
userID: 1234,
type: "photo",
photo: {
"title": "Photo",
"src": "/photo.jpg"
}
}, {
name: "John",
userID: 1234,
type: "photo",
photo: {
"title": "Photo",
"src": "/photo.jpg"
}
}];
const merged = merge(obj);
document.getElementById('out').textContent = JSON.stringify(merged, null, 2);
console.log(merged);
<pre id="out"></pre>
答案 3 :(得分:1)
解决方案是
在ES6中
// Transform
let new_users = user.map(u => {
let o = Object.assign({}, u, {photos: [u.photo]}));
delete o.photo;
return o;
});
// Sort by user ID
new_users = new_users.sort((a,b) => a.userID - b.userID);
// Merge on userID
let prev = null;
new_user = new_user.filter(u => {
if (prev && prev.userID === u.userID) {
prev.photos.push(u.photos[0]);
return false;
}
prev = u;
return true;
});