skip to Main Content

I want to merge arrays of the same type. It comes from the database as follows.

const array =[
{
  name: 'Iphone',
  date: '01.01.2024',
  img: 'img/iphone.png',
  cost: 2500,
  username:"Joe",
},
{
  name: 'Samsung',
  date: '01.01.2024',
  img: 'img/samsung.png',
  cost: 2000,
  username:"Adam",
},
{
  name: 'Samsung',
  date: '01.01.2024',
  img: 'img/samsung.png',
  cost: 2000,
  username:"Alvin",
}
]

I need to convert it to the following array?

const array =[
{
  name: 'Iphone',
  date: '01.01.2024',
  img: 'img/iphone.png',
  cost: 2500,
  username:"Joe",
},
{
  name: 'Samsung',
  date: '01.01.2024',
  img: 'img/samsung.png',
  cost: 2000,
  usernames:[{
    username:"Adam"
  },
  {
    username:"Alvin"
  }]
  ,
},
]

Can you help me please?

4

Answers


  1. First, get the unique phone names.

    Then, for each name, find the matching phone entry, and extract all properties in to a new object. Then, add in all usernames for that phone name.

    Finally, if there is more than one username, delete the username property for each object in the resulting array, so that there is only a usernames property at the top level. Otherwise, keep only the username property and delete the usernames property.

    const array = [{"name":"Iphone","date":"01.01.2024","img":"img/iphone.png","cost":2500,"username":"Joe"},{"name":"Samsung","date":"01.01.2024","img":"img/samsung.png","cost":2000,"username":"Adam"},{"name":"Samsung","date":"01.01.2024","img":"img/samsung.png","cost":2000,"username":"Alvin"}]
    
    let names = [...new Set(array.map(i=>i.name))]
    
    let array2 = names.map(name => ({
      ...array.find(i => i.name===name),
      usernames: array.filter(i => i.name===name)
                      .map(({username}) => ({username})),
    }))
    
    array2.forEach(i => 
      delete i.usernames.length > 1 ? i.username : i.usernames
    )
    
    console.log(array2)
    Login or Signup to reply.
  2. const data = [
        {
            name: 'Iphone',
            date: '01.01.2024',
            img: 'img/iphone.png',
            cost: 2500,
            username: 'Joe',
        },
        {
            name: 'Samsung',
            date: '01.01.2024',
            img: 'img/samsung.png',
            cost: 2000,
            username: 'Adam',
        },
        {
            name: 'Samsung',
            date: '01.01.2024',
            img: 'img/samsung.png',
            cost: 2000,
            username: 'Alvin',
        },
    ];
    
    const processedData = data.reduce((acc, curr) => {
        const found = acc.find(
            (user) =>
                user.name === curr.name &&
                user.date === curr.date &&
                user.img === curr.img &&
                user.cost === curr.cost
        );
    
        if (found) {
            found.usernames.push({ username: curr.username });
        } else {
            acc.push({
                name: curr.name,
                date: curr.date,
                img: curr.img,
                cost: curr.cost,
                usernames: [{ username: curr.username }],
            });
        }
    
        return acc;
    }, []);
    

    This code uses the reduce function to iterate through the initial array and create a new array (resultArray) in the desired format by checking if an object with the same ‘name’, ‘date’, ‘img’, and ‘cost’ already exists in the accumulator (acc). If it exists, it pushes the ‘username’ to the ‘usernames’ array. Otherwise, it creates a new object and initializes the ‘usernames’ array with the current ‘username’.

    Login or Signup to reply.
  3. I suggest to use a simple array for the usernames. That accepted, a possible solution could look like this:

    const arr =[
    {
      name: 'Iphone',
      date: '01.01.2024',
      img: 'img/iphone.png',
      cost: 2500,
      username:"Joe",
    },
    {
      name: 'Samsung',
      date: '01.01.2024',
      img: 'img/samsung.png',
      cost: 2000,
      username:"Adam",
    },
    {
      name: 'Samsung',
      date: '01.01.2024',
      img: 'img/samsung.png',
      cost: 2000,
      username:"Alvin",
    }];
    
    const res=Object.values(arr.reduce((a,c)=>{
     const k=c.name+c.date+c.img+c.cost;
     if (!a[k]){ a[k]={...c, usernames:[]}; delete a[k].username;}
     a[k].usernames.push(c.username);
     return a;
    },{}));
    
    console.log(res);
    Login or Signup to reply.
  4. For performance, build a tree of property values with the leaves being object unique by all fields except username:

    const result = array.reduce((r, {username, ...item}) => {
      r.keys ??= Object.keys(item);
      r.lastKey ??= r.keys.pop();
      let node = r.cached;
      for(const key of r.keys){
        node = node[item[key]] ??= {};
      }
      const found = node[item[r.lastKey]];
      if(!found){
         r.arr[r.arr.length] = node[item[r.lastKey]] = Object.assign(item, {username});
      }else{
         found.usernames?.push({username}) ?? (found.usernames = [{username: found.username}, {username}]);
      }
      return r;
    }, 
    {cached: {}, arr: []}).arr;
    
    console.log(result);
    <script>
    const array=[{name:"Iphone",date:"01.01.2024",img:"img/iphone.png",cost:2500,username:"Joe"},{name:"Samsung",date:"01.01.2024",img:"img/samsung.png",cost:2e3,username:"Adam"},{name:"Samsung",date:"01.01.2024",img:"img/samsung.png",cost:2e3,username:"Alvin"}];
    </script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search