1

I am creating a project using JavaScript. I am stuck in the problem while filtering the array of object: Here is the array:

var arr1 = [{
      "name": "harkaran",
      "lname": "sofat",
      "userId": 49,
     "postedUserId": 52,
      "id": 21,

    },{
      "name": "harkaran",
      "lname": "sofat",
      "userId": 49,
      "postedUserId": 57,
      "id": 21,
    }]

final array should look like:

[{
    "name": "harkaran",
      "lname": "sofat",
      "userId": 49,
     "postedUserId": 52,
      "id": 21,
      postedUsers:[52,57]
}] 

I am trying to creating new object. Here is the approach i am using.But dont know how can i achieve this var arr =[] let obj = {}

        obj['name'] = "";
        obj['lname'] = "";
        obj['userId'] = "";
        obj['postedUserId'] = "";
        obj['id'] = "";
        obj['postedUsers'] = [];
        arr.push(obj);

        for(var i=0; i<arr1.length; i++){


         }
Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
Karan
  • 1,048
  • 2
  • 20
  • 38

4 Answers4

1

Use reduce:

var arr1 = [{"name":"harkaran","lname":"sofat","userId":49,"postedUserId":52,"id":21,},{"name":"harkaran","lname":"sofat","userId":49,"postedUserId":57,"id":21,}];
const res = Object.values(arr1.reduce((acc, { postedUserId, name, ...rest }) => {
  acc[name] = acc[name] || { name, ...rest, postedUserId, postedUsers: [] };
  acc[name].postedUsers = [].concat(acc[name].postedUsers, postedUserId);
  return acc;
}, {}));
console.log(res);
.as-console-wrapper { max-height: 100% !important; top: auto; }
Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
1

First of all this is not called filtering. Its called grouping. You can do that in following steps:

  • First use reduce() on array and set accumulator to an empty object {}
  • During each iteration get id and postedUserId is separate variable using Destructuring. And use spread operator to get rest of properties.
  • Then check if is there already an item present of the current id in accumulator.
  • If its there then push the postedUserId to its postedUsers array.
  • If that key is not present then set the key(id) on accumulator to an object with postedUsers as empty array.

var arr1 = [{"name":"harkaran","lname":"sofat","userId":49,"postedUserId":52,"id":21,},{"name":"harkaran","lname":"sofat","userId":49,"postedUserId":57,"id":21,}];

const res = arr1.reduce((ac,{id,postedUserId,...rest}) => {
  if(!ac[id]) ac[id] = {id,postedUserId,postedUsers:[],...rest};
  ac[id].postedUsers.push(postedUserId);
  return ac;

},{})

console.log(Object.values(res))

You asked in the comments for simple for loop so here is the version of that.

var arr1 = [{"name":"harkaran","lname":"sofat","userId":49,"postedUserId":52,"id":21,},{"name":"harkaran","lname":"sofat","userId":49,"postedUserId":57,"id":21,}];

let res = {};

for(let i = 0; i<arr1.length; i++){
  let {id,postedUserId,...rest} = arr1[i];
  if(!res[id]) res[id] = {id,postedUserId,postedUsers:[],...rest};
  res[id].postedUsers.push(postedUserId);
}

console.log(Object.values(res))
Maheer Ali
  • 35,834
  • 5
  • 42
  • 73
  • You missed `postedUserId` in final output mate – Code Maniac Jun 09 '19 at 07:39
  • 1
    @CodeManiac You are right but I consider OP had put that mistakenly. Because there is no point to have `postedUserId` when there is an array of `postedUsers` – Maheer Ali Jun 09 '19 at 07:41
  • that's clearly mentioned by OP in comments so i pointed out [Ref](https://stackoverflow.com/questions/56512709/filter-array-of-object-in-javascript/56512807#comment99611827_56512709) – Code Maniac Jun 09 '19 at 07:43
0

You can use reduce and group the postedUser and keep the first postedUserId

  • First loop through arr1 array and use id as key on object we are building
  • First we check for the id if the object already has value, than check for postedUserId if it's not there add the current id else don't
  • Now push the postedUserId in postedUser
  • Get the values from final in the end

var arr1 = [{"name": "harkaran","lname": "sofat","userId": 49,"postedUserId": 52,"id": 21,}, {"name": "harkaran","lname": "sofat","userId": 49,"postedUserId": 57,"id": 21,}]

let final = arr1.reduce((op,{id,...rest})=>{
  let postedUserId = rest.postedUserId
  if(op[id] && op[id].postedUserId){
    delete rest.postedUserId
  }
  op[id] = op[id] || {...rest,postedUser:[]}
  op[id].postedUser.push(postedUserId)
  return op
},{})

console.log(Object.values(final))
Code Maniac
  • 37,143
  • 5
  • 39
  • 60
0

I would use a temporary Map for the grouping you want.

var arr1 = [{"name":"harkaran","lname":"sofat","userId":49,"postedUserId":52,"id":21,},{"name":"harkaran","lname":"sofat","userId":49,"postedUserId":57,"id":21,}];

const map = new Map(arr1.map(o => [o.id, { ...o, postUsersId: [] }]));
arr1.forEach(o => map.get(o.id).postUsersId.push(o.postedUserId));
const res = [...map.values()];

console.log(res);

This will give precedence to the data given with the last occurrence of the same id. If you want the first to have precedence, then just reverse the array

trincot
  • 317,000
  • 35
  • 244
  • 286