0

I am working on a javascript program and I need an object to return to the frontend.

I wrote some queries that return:

  • photos: array of {id, owner, link, description, name}
  • comments: array of {id, text, photoTarget, userOrigin, name } //photoTraget is the photo id

I want to create a new array called photoArray, which has the comments for each photo stored as a subarray.

This is the structure :

photoArray[0] ={
        id, 
        owner, 
        link, 
        description, 
        name, 
        comment: [id, text, photoTarget, userOrigin, name]
      }

approach:

for(var i=0; i< photos.length; i++){
   for(var j=0; j< comments.length; j++){
      if(photos[i].id == comments[j].photoTarget){

              //I can't get this part to work

       }
   }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Razvan Olariu
  • 59
  • 1
  • 8
  • this gives some interesting information on working with arrays of objects. https://stackoverflow.com/questions/12462318/find-a-value-in-an-array-of-objects-in-javascript – user1238097 Jan 06 '19 at 16:33
  • @Razvan Olariu check out my answer below, I have used array.reduce and array.map to achieve what you want – Karthikeyan Jan 06 '19 at 17:30

5 Answers5

0

You could use a Map by reducing the photos array, where a new property comments is assigned, which is the value of the map.

Then iterate comments and push the data to the assigned poto map.

This approach uses only two loops, Big O: O(n + m)

var photos = [{...}, {...}, ...],
    comments = [{...}, {...}, ...],
    photoMap = photos.reduce((m, p) => m.set(p.id, p.comments = []), new Map);


comments.forEach(c => photoMap.get(c.photoTarget).push(p));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • If for some reason the comments array has an element with a photoTarget value that is not present in the photos array, then photoMap.get(c.photoTarget).push(p) will fail. – Karthikeyan Jan 06 '19 at 17:26
  • @Karthikeyan, right, but i assume there are no holes. but even if so, then by iteraiting comments, it could assign a new data set to `photos` and addthe id to the map as as well. – Nina Scholz Jan 06 '19 at 17:31
0

First you need to add comments array as a property to the image object

for (var i = 0; i < photos.length; i++) {
   photos[i].comments = [];
}

Then

for(var i=0; i< photos.length; i++){
  for(var j=0; j< comments.length; j++){
     if(photos[i].id == comments[j].photoTarget){
       photos[i].comments.push({comments[j].id, comments[j].text, 
       comments[j].photoTarget, comments[j].userOrigin, comments[j].name});
    }
  }
}
Amr Aly
  • 26
  • 2
  • 3
0

Iterate through the photos array and find the matching comment and add it to the comment array of the photo object.

var photos =  [{id :1, owner:'test'}]
var comments = [{id:1, text:'test', photoTarget:1}, {id:2, text:'test1', photoTarget:1}]
var photoArray = []

for(var i=0; i< photos.length; i++){
   var photo = photos[i];
   for(var j=0; j< comments.length; j++){
      if(photos[i].id == comments[j].photoTarget){
              photo.comment = photo.comment ? photo.comment.concat(comments[j]) : [].concat(comments[j]); //Add a comment property and assign the matching comment object
              
       }
     }
      photoArray.push(photo);
}

console.log(JSON.stringify(photoArray));
Fullstack Guy
  • 16,368
  • 3
  • 29
  • 44
0

One approach can be to filter comment objects for each photo based on photoTarget as you're building the final array:

const result = photos.map(p =>
  Object.assign({}, p, { comments: comments.filter(c => c.photoTarget === p.id) }));

A demo with simplified objects is below:

const photos = [{"id":1,"owner":"Spence","name":"eiusmod ex"},{"id":2,"owner":"Billie","name":"ullamco officia"},{"id":3,"owner":"Shannon","name":"duis ipsum"},{"id":4,"owner":"Marian","name":"excepteur ipsum"}];;
const comments = [{"id":0,"name":"Kendra","text":"reprehenderit sit sunt Lorem","photoTarget":3},{"id":1,"name":"Arline","text":"nisi aliqua in magna","photoTarget":4},{"id":2,"name":"Earlene","text":"proident ex cupidatat eu","photoTarget":3},{"id":3,"name":"Downs","text":"ullamco est veniam enim","photoTarget":1},{"id":4,"name":"Claire","text":"voluptate tempor velit laborum","photoTarget":4},{"id":5,"name":"Louise","text":"amet ea quis ipsum","photoTarget":2},{"id":6,"name":"Simpson","text":"qui velit in enim","photoTarget":1},{"id":7,"name":"Lavonne","text":"ea qui mollit adipisicing","photoTarget":4},{"id":8,"name":"Morris","text":"veniam aliquip esse nisi","photoTarget":1},{"id":9,"name":"Rosalinda","text":"consequat non culpa qui","photoTarget":2}];

const result = photos.map(p =>
  Object.assign({}, p, { comments: comments.filter(c => c.photoTarget === p.id) }));

console.log(result);

This approach is slower than using something like a Map as it iterates through all comments for each photo.

slider
  • 12,810
  • 1
  • 26
  • 42
0

I have reduced the comments array into a commentsGroupedByPhoto ( an object where photoTarget will be the key and an array of comments having the same photoTarget) and then used map function on photos to generate photoArray leaving the photos array unmodified

var photos =  [{id :1, owner:'owner1'},{id :2, owner:'owner2'},{id:3,owner:'owner3'}]
var comments = [{id:1, text:'comment1 for 1', photoTarget:1, userOrigin: 'Asia'}, {id:2, text:'comment2 for 1', photoTarget:1, userOrigin: 'America'}, {id:3, text:'only comment for 2', photoTarget:2, userOrigin: 'Europe'}]
var commentsGroupedByPhoto = comments.reduce(function(commentsObj, comment) {
  var photoId = comment.photoTarget,
  commentByPhotoTarget = commentsObj[photoId];
  commentByPhotoTarget ? commentByPhotoTarget.push(comment) : commentsObj[photoId] = [comment];
  return commentsObj;
}, {});

console.log('comments grouped by id --- ' + JSON.stringify(commentsGroupedByPhoto));

var photoArray = photos.map(function(photo){
  var photoCopy = {photo}; //ES6 cloning
  //if your codebase does not support ES6 then use
  //var photoCopy = Object.assign({}, photo);
  photoCopy.comments = commentsGroupedByPhoto[photo.id];
  return photoCopy;
});

console.log('photoArray --- ' + JSON.stringify(photoArray));
console.log('photos --- ' + JSON.stringify(photos));
Karthikeyan
  • 302
  • 1
  • 11