StormTrooper
StormTrooper

Reputation: 1573

javascript - concat two arrays but with identical objects

I have this array of all users:

let allUsers = [
    {
        id: 1,
        name: "Mike"
    },
    {
        id: 2,
        name: "John"
    },
    {
        id: 3,
        name: "Kim"
    },
    {
        id: 4,
        name: "Mike"
    }
];

Now I have array of batches. Each batch has its own users array.

const userBatches = [
    {   
        "batchId": 1,
        "users": [
            {
                id: 5,
                name: "Max"
            },
            {
                id: 2,
                name: "Simon"
            }
        ]
    },
    {   
        "batchId": 2,
        "users": [
            {
                id: 6,
                name: "Max"
            },
            {
                id: 7,
                name: "Conor"
            }
        ]
    },
    {   
        "batchId": 3,
        "users": [
            {
                id: 3,
                name: "Norman"
            }
        ]
    }
]

Here I want to push only those users that does not exists in allUsers array. (on the basis of user id not name)

In simple words allUsers should contain the unique users. No duplicates.

Expected response of allUsers:

[
    {
        id: 1,
        name: "Mike"
    },
    {
        id: 2,
        name: "John"
    },
    {
        id: 3,
        name: "Kim"
    },
    {
        id: 4,
        name: "Mike"
    },
    {
        id: 5,
        name: "Max"
    },
    {
        id: 6,
        name: "Max"
    },
    {
        id: 7
        name: "Conor"
    }
]

Here is the attached code snippet:

let allUsers = [
    {
        id: 1,
        name: "Mike"
    },
    {
        id: 2,
        name: "John"
    },
    {
        id: 3,
        name: "Kim"
    },
    {
        id: 4,
        name: "Mike"
    }
];

const userBatches = [
    {   
        "batchId": 1,
        "users": [
            {
                id: 5,
                name: "Max"
            },
            {
                id: 2,
                name: "Simon"
            }
        ]
    },
    {   
        "batchId": 2,
        "users": [
            {
                id: 6,
                name: "Max"
            },
            {
                id: 7,
                name: "Conor"
            }
        ]
    },
    {   
        "batchId": 3,
        "users": [
            {
                id: 3,
                name: "Norman"
            }
        ]
    }
];

userBatches.forEach((batch) => {
    
  console.log(batch)
    // if batch users does not exists allUsers array then add these users to allUsers array 
});

Upvotes: 1

Views: 73

Answers (4)

gog
gog

Reputation: 11347

An efficient solution would be to create a map id=>user and populate it from both arrays:

uniqueUsers = [...new Map([
    ...allUsers.map(u => [u.id, u]),
    ...userBatches.flatMap(b => b.users).map(u => [u.id, u])
]).values()];

Upvotes: 0

AltDan
AltDan

Reputation: 844

Here’s one possible solution using the array method filter:

const uniqueUsers = userBatches.flatMap(batch => batch.users)
  .filter(user => !allUsers.some(u => u.id === user.id))
  .concat(allUsers);

console.log(uniqueUsers);

// Output: [
// { id: 1, name: 'Mike' },
// { id: 2, name: 'John' },
// { id: 3, name: 'Kim' },
// { id: 4, name: 'Mike' },
// { id: 5, name: 'Max' },
// { id: 6, name: 'Max' },
// { id: 7, name: 'Conor' }
// ]

Upvotes: 3

Harun Yilmaz
Harun Yilmaz

Reputation: 8558

You can use Array.some() to see if the array has the object by comparing the IDs, as follows:

let allUsers = [{
    id: 1,
    name: "Mike"
  },
  {
    id: 2,
    name: "John"
  },
  {
    id: 3,
    name: "Kim"
  },
  {
    id: 4,
    name: "Mike"
  }
];

const userBatches = [{
    "batchId": 1,
    "users": [{
        id: 5,
        name: "Max"
      },
      {
        id: 2,
        name: "Simon"
      }
    ]
  },
  {
    "batchId": 2,
    "users": [{
        id: 6,
        name: "Max"
      },
      {
        id: 7,
        name: "Conor"
      }
    ]
  },
  {
    "batchId": 3,
    "users": [{
      id: 3,
      name: "Norman"
    }]
  }
];

userBatches.forEach((batch) => {
  batch.users.forEach(user => {
    if (!allUsers.some(u => u.id === user.id)) {
      allUsers.push(user)
    }
  })
});

console.log(allUsers)


Option 2:

If you want to avoid nested Array.forEach(), you can use Array.filter() and the spread operator. But note that this way you are creating a new array in each iteration

let allUsers = [{
    id: 1,
    name: "Mike"
  },
  {
    id: 2,
    name: "John"
  },
  {
    id: 3,
    name: "Kim"
  },
  {
    id: 4,
    name: "Mike"
  }
];

const userBatches = [{
    "batchId": 1,
    "users": [{
        id: 5,
        name: "Max"
      },
      {
        id: 2,
        name: "Simon"
      }
    ]
  },
  {
    "batchId": 2,
    "users": [{
        id: 6,
        name: "Max"
      },
      {
        id: 7,
        name: "Conor"
      }
    ]
  },
  {
    "batchId": 3,
    "users": [{
      id: 3,
      name: "Norman"
    }]
  }
];

userBatches.forEach((batch) => {
  allUsers = [...allUsers, ...batch.users.filter(user => !allUsers.some(u => u.id === user.id))]
});

console.log(allUsers)

Upvotes: 0

Layhout
Layhout

Reputation: 1580

let allUsers = [{
    id: 1,
    name: "Mike"
  },
  {
    id: 2,
    name: "John"
  },
  {
    id: 3,
    name: "Kim"
  },
  {
    id: 4,
    name: "Mike"
  }
];

const userBatches = [{
    "batchId": 1,
    "users": [{
        id: 5,
        name: "Max"
      },
      {
        id: 2,
        name: "Simon"
      }
    ]
  },
  {
    "batchId": 2,
    "users": [{
        id: 6,
        name: "Max"
      },
      {
        id: 7,
        name: "Conor"
      }
    ]
  },
  {
    "batchId": 3,
    "users": [{
      id: 3,
      name: "Norman"
    }]
  }
];

userBatches.forEach(ub => {
  ub.users.forEach(ubu => {
    if (!allUsers.some(au => au.id === ubu.id)) allUsers.push(ubu)
  })
})

console.log(allUsers);

Upvotes: 0

Related Questions