Push array in object if some keys are same in javascript

I have an code some like this ;

 var data = [
 {'times':'07:50','name':'bojes'},
 {'times':'07:50','name':'unknw1q2q'},
 {'times':'09:50','name':'rafik'},
 {'times':'11:50','name':'adit'},
 {'times':'15:50','name':'adit'},
 {'times':'15:50','name':'adrok'}
  ]; 

i will grouping the object 'name' and push it into a new array if the 'times' is same. I know its like playing array.reduce, findWhere in underscore js or something bad like that, but my logic is bad.

And i will happy if you will output my code like this ;

var newData = [
 {'times':'07:50','name': ['bojes','unknw1q2q'] },
 {'times':'09:50','name': ['rafik'] },
 {'times':'11:50','name': ['adit'] },
 {'times':'15:50','name': ['adit','adrok'] },
  ]; 

how can i did it ? some people wanna help me ? thx before it

3 answers

  • answered 2018-10-22 18:36 brk

    You can use reduce & findIndex.Use reduce to create a new array(map can also be used). Using findIndex get the index of the object from array where the times matches. If so then update the name array else create a new object and push in the accumulator array

    var data = [{
        'times': '07:50',
        'name': 'bojes'
      },
      {
        'times': '07:50',
        'name': 'unknw1q2q'
      },
      {
        'times': '09:50',
        'name': 'rafik'
      },
      {
        'times': '11:50',
        'name': 'adit'
      },
      {
        'times': '15:50',
        'name': 'adit'
      },
      {
        'times': '15:50',
        'name': 'adrok'
      }
    ];
    
    let k = data.reduce(function(acc, curr) {
      // check if the times is present
    
      let findIndex = acc.findIndex(function(item) {
        return item.times === curr.times
      })
    
      if (findIndex == -1) {
        let obj = Object.assign({}, {
          times: curr.times,
          name: [curr.name]
        })
        acc.push(obj)
      } else {
        acc[findIndex].name.push(curr.name)
      }
    
      return acc;
    }, []);
    
    console.log(k)

  • answered 2018-10-22 18:40 Mark Meyer

    You can do this efficiently by creating an object keyed to the thing you want to be unique —— times in this case. For each time create an object with an array to hold your values. At the end the Object.values() of the object will be what you want. This will be more efficient that searching the list each time for a duplicate:

    var data = [{'times':'07:50','name':'bojes'},{'times':'07:50','name':'unknw1q2q'},{'times':'09:50','name':'rafik'},{'times':'11:50','name':'adit'},{'times':'15:50','name':'adit'},{'times':'15:50','name':'adrok'}];
    
    let res = Object.values(data.reduce((obj, curr) => {
        // if we haven't seen the time before make a new entry
        if(!obj[curr.times]) obj[curr.times] = {times: curr.times, name: []}
        // push the current name into the current time entry
        obj[curr.times]['name'].push(curr.name)
        return obj
    }, {}))
    console.log(res)

  • answered 2018-10-22 18:49 Scott Rudiger

    Here's one way you could do it using Object.values and Array#reduce:

    const data = [
      {'times':'07:50','name':'bojes'},
      {'times':'07:50','name':'unknw1q2q'},
      {'times':'09:50','name':'rafik'},
      {'times':'11:50','name':'adit'},
      {'times':'15:50','name':'adit'},
      {'times':'15:50','name':'adrok'}
    ];
    
    const groupByTimes = data => Object.values(data.reduce((data, {times, name}) => {
      if (data[times]) data[times].name.push(name);
      else data[times] = {times, name: [name]};
      return data;
    }, {}));
    
    console.log(groupByTimes(data));

    Alternatively, using Object.assign:

    const data = [
      {'times':'07:50','name':'bojes'},
      {'times':'07:50','name':'unknw1q2q'},
      {'times':'09:50','name':'rafik'},
      {'times':'11:50','name':'adit'},
      {'times':'15:50','name':'adit'},
      {'times':'15:50','name':'adrok'}
    ];
    
    const groupByTimes = data => Object.values(
      data.reduce((data, {times, name}) => Object.assign({}, data, {
        [times]: data[times]
          ? {times, name: [...data[times].name, name]}
          : {times, name: [name]}
      }), {})
    );
    
    console.log(groupByTimes(data));

    Or, with object spread syntax:

    const data = [
      {'times':'07:50','name':'bojes'},
      {'times':'07:50','name':'unknw1q2q'},
      {'times':'09:50','name':'rafik'},
      {'times':'11:50','name':'adit'},
      {'times':'15:50','name':'adit'},
      {'times':'15:50','name':'adrok'}
    ];
    
    const groupByTimes = data => Object.values(
      data.reduce((data, {times, name}) => ({
        ...data,
        [times]: data[times]
          ? {times, name: [...data[times].name, name]}
          : {times, name: [name]}
      }), {})
    );
    
    console.log(groupByTimes(data));