1

I have array like this.

[{first_name: "john", age: "30", institution: {id: 1, name: "inst1"}},
 {first_name: "john", age: "30", institution: {id: 2, name: "inst2"}},
 {first_name: "john", age: "30", institution: {id: 3, name: "inst3"}}]

I want to check if values are same except institution then i want to generate a array like this

[{first_name: "john", age: "30", institution:{name: "inst1, inst2, inst3"}}]
qiAlex
  • 4,290
  • 2
  • 19
  • 35
User99
  • 129
  • 1
  • 11

7 Answers7

1

What you want to do is some sort of grouping followed by reduce. es6 does not provide groupBy function out of the box. But you can use reduce to achieve the same behavior.

Steps

Source Array --> Group By Person --> Join the institution names

Implemented Solution

In your case:

const arr = [{first_name: "john", age: "30", institution: {id: 1, name: "inst1"}},
 {first_name: "john", age: "30", institution: {id: 2, name: "inst2"}},
 {first_name: "john", age: "30", institution: {id: 3, name: "inst3"}}];


const result = arr.reduce((ac, person) => {
  // check for the existing person in the accumulator
  const existingRecord = ac.find(existingPerson => existingPerson.first_name === person.first_name)

  // if. exists, concatenate the institution
  if (existingRecord) {
    existingRecord.institution += `, ${person.institution.name}`;
    return ac;
  // otherwise, add this as a new person
  } else {
    return [...ac, {
      first_name: person.first_name,
      age: person.age,
      institution: person.institution.name
    }]
  }
}, []);

More general approach to implement a group by:

Most efficient method to groupby on an array of objects

You can also use Lodash which provides more options

evolon
  • 1,276
  • 1
  • 10
  • 18
0

you can try this

const arr = [{first_name: "john", age: "30", institution: {id: 1, name: "inst1"}},
 {first_name: "john", age: "30", institution: {id: 2, name: "inst2"}},
 {first_name: "john", age: "30", institution: {id: 3, name: "inst3"}}];

const result = arr.reduce((acc, item) => {
  const itemInAcc = acc.find(itemAcc => itemAcc.first_name === item.first_name && itemAcc.age === item.age);
  
  if (!itemInAcc) {
    acc.push({...item, institution: {name: item.institution.name}})
  } else {
    itemInAcc.institution.name = [itemInAcc.institution.name, item.institution.name].join(`, `)
  }
  return acc;
}, []);

console.log(result); // [{first_name: "john", age: "30", institution: {name: "inst1, inst2, inst3"}}]
qiAlex
  • 4,290
  • 2
  • 19
  • 35
  • what to do ? if i want output like this [{first_name: "john", age: "30", institution:{name:"inst1, inst2 inst3"}}] – User99 Feb 05 '20 at 12:23
  • can you please clarify what is the difference between output in my example and yours? I can see only difference in `"institution": "inst1, inst2, inst3"` - 2 commas, and in your comment - ` institution:{name:"inst1, inst2 inst3"} ` - one comma. is there any other difference? – qiAlex Feb 05 '20 at 12:31
  • Sorry, comma i removed mistakenly. i want to assign values to name attribute. like institution:{name: "inst1, inst2, inst3"}. if you read question again so i updated there as well. – User99 Feb 05 '20 at 12:37
  • This answer is inefficient because it performs a brute force search inside a loop. – Ben Aston Feb 05 '20 at 12:46
0

Please use The below Code .

let obj = [{
    first_name: "john",
    age: "30",
    institution: {
      id: 1,
      name: "inst1"
    }
  },
  {
    first_name: "john",
    age: "30",
    institution: {
      id: 2,
      name: "inst2"
    }
  },
  {
    first_name: "john",
    age: "30",
    institution: {
      id: 3,
      name: "inst3"
    }
  }
]
let newObj = []

let isSame = true;
let obj1 = {}
let obj2 = {}
obj.forEach((o, i) => {

  if (i + 1 < obj.length) {
    obj1 = {
      fn: obj[i].first_name,
      age: obj[i].age
    }
    obj2 = {
      fn: obj[i + 1].first_name,
      age: obj[i + 1].age
    }
    if (JSON.stringify(obj1) !== JSON.stringify(obj2) ){
     isSame = false;
    }
  }

})

if(isSame){
let anotherobj = {}
 let fn = obj[0].first_name
  let age = obj[0].age;
  let instiValue=''
  obj.forEach(o=>{
   instiValue = instiValue + o.institution.name + ", ";
  })
  anotherobj.first_name = fn;
  anotherobj.age = age;
  anotherobj.institution = instiValue;
  
  newObj.push(anotherobj);
}

console.log(newObj)
Ashish
  • 410
  • 2
  • 11
0

This might help.

const data = [{first_name: "john", age: "30", institution: {id: 1, name: "inst1"}},
              {first_name: "john", age: "30", institution: {id: 2, name: "inst2"}},
              {first_name: "john", age: "30", institution: {id: 3, name: "inst3"}}]

console.log(
    Object.values(
        data.reduce((p,{ institution: { name }, ...r }, _, __, k = r) =>
            ((p[k] ? (p[k].institution.name += `, ${name}`) 
                   : p[k] = ({ ...r, institution: { name }  })), p),{})))
Ben Aston
  • 53,718
  • 65
  • 205
  • 331
0

you can generate a key combining the attributes first_name and age, and use them in a Map Object then convert the result back to an array

const items = [
    {first_name: "john", age: "30", institution: {id: 1, name: "inst1"}},
    {first_name: "john", age: "30", institution: {id: 2, name: "inst2"}},
    {first_name: "john", age: "30", institution: {id: 3, name: "inst3"}}];

const key = item => `${item.first_name}:${item.age}`;

const unique = new Map(items.map(item => [key(item), item]))
const result = Array.from(unique.values())
sney2002
  • 856
  • 3
  • 6
  • It's likely not a problem with `name` and `age`, but combining fields like this without some separator not likely to appear in either can cause problems. Think of combining `first` and `last` names for `{first: 'jon', last: 'isling'}` and `{first: 'joni', last: 'sling'}`. Just putting a separator such as `/` or `~` between the fields reduces the chance drastically. – Scott Sauyet Feb 05 '20 at 13:27
  • 1
    @ScottSauyet Yeah, I didn't use a separator because it is a name and an age. I updated the answer to use a separator. – sney2002 Feb 05 '20 at 13:58
0

if you use React.js

you can try this:

App.js

// App.js

import React from "react";
import { addItemToUser } from "./utiles";

export default class App extends React.Component {
  state = {
    users: [
      { first_name: "john", age: "30", institution: { id: 1, name: "inst1" } },
      { first_name: "mike", age: "20", institution: { id: 2, name: "inst2" } },
      { first_name: "ali", age: "40", institution: { id: 3, name: "inst3" } }
    ]
  };

  render() {
    const newUser = {
      first_name: "john",
      age: "30",
      institution: { id: 1, name: "inst2" }
    };
    const userList = addItemToUser(this.state.users, newUser);
    console.log(userList);
    return (
      <div className="App">please check your console</div>
    );
  }
}

utiles.js

// utiles.js

export const addItemToUser = (users, userItemToAdd) => {
  const existingUserItem = users.find(
    user => user.first_name === userItemToAdd.first_name
  );

  if (existingUserItem) {
    return users.map(user =>
      user.first_name === userItemToAdd.first_name
        ? { ...user, institution: { name: user.institution.name + ', ' + userItemToAdd.institution.name } }
        : user
    );
  }

  return [...users, { ...userItemToAdd }];
};
Mohammad Oftadeh
  • 1,410
  • 1
  • 4
  • 11
0

Please check this code-

let a = [{ first_name: "john", age: "30", institution: { id: 1, name: "inst1" } },
{ first_name: "john", age: "30", institution: { id: 2, name: "inst2" } },
{ first_name: "mohan", age: "20", institution: { id: 2, name: "inst2" } },
{ first_name: "john", age: "30", institution: { id: 3, name: "inst3" } }];

let b = [];
for (var i = 0; i < a.length; i++) {
    if (b.length != 0) {

        let j_val = '';
        let flag = false;

        for (let j = 0; j < b.length; j++) {
            if ((a[i].first_name == b[j].first_name) && (a[i].age == b[j].age)) {
                j_val = j;
                flag = true;
            } else {

            }

        }
        let cc = a[i].institution.name;
        if (flag) {
            b[j_val].institution.name = b[j_val].institution.name + "," + cc;
        } else {
            b.push({ first_name: a[i].first_name, age: a[i].age, institution: { name: a[i].institution.name } });
        }
    } else {
        b.push({ first_name: a[i].first_name, age: a[i].age, institution: { name: a[i].institution.name } });
    }

}

console.log(b)