jasmeetsohal
jasmeetsohal

Reputation: 141

Find max date from Array of Objects and update by adding flag in Javascript

Underneath is an array of objects containing two properties emp_name and date and I want to update records by adding flag in which date should be greatest among other date corresponding to emp_name.

let arr_of_obj = [{emp_name:'Mark',date:new Date('2018/05/01')},
                  {emp_name:'Mark',date:new Date('2018/05/02')},
                  {emp_name:'John',date:new Date('2018/04/05')},
                  {emp_name:'John',date:new Date('2018/03/22')},
                  {emp_name:'Mark',date:new Date('2018/05/06')}];

Suppose above arr_of_obj should updated two entries i.e.

[{emp_name:'Mark',date:new Date('2018/05/21')},
{emp_name:'Mark',date:new Date('2018/05/22')},
{emp_name:'John',date:new Date('2018/04/15'),max:true},
{emp_name:'John',date:new Date('2018/03/22')},
{emp_name:'Mark',date:new Date('2018/05/26'),max:true}]

Upvotes: 0

Views: 368

Answers (4)

Logar
Logar

Reputation: 1248

Not bringing much more than @Engineer but I tend to avoid declaring const and then assigning properties to it, even if it's not a big deal. So I like using reduce here :

const max_dates = arr_of_obj.reduce((stored, item) => {
    if(!stored[item.emp_name] || stored[item.emp_name].date < item.date)
        stored[item.emp_name] = item;
    return stored;
}, {});


Object.values(max_dates).map(item => item.max = true)

Upvotes: 1

Alexander Kahoun
Alexander Kahoun

Reputation: 2488

let arr_of_obj = [{
    emp_name: 'Mark',
    date: new Date('2018/05/01')
  },
  {
    emp_name: 'Mark',
    date: new Date('2018/05/02')
  },
  {
    emp_name: 'John',
    date: new Date('2018/04/05')
  },
  {
    emp_name: 'John',
    date: new Date('2018/03/22')
  },
  {
    emp_name: 'Mark',
    date: new Date('2018/05/06')
  }
];

console.log('initial array', arr_of_obj);

const max_items = arr_of_obj.map((o, i) => {
  return {
    ord: i,
    emp_name: o.emp_name,
    date: o.date
  };
}).sort((a, b) => b.date - a.date).reduce((l, r) => {
  if (!Array.isArray(l)) {
    if (l.emp_name === r.emp_name) return l.date > r.date ? [l] : [r];
    return [l, r];
  }
  const last = l.slice(-1)[0];
  if (last.emp_name === r.emp_name) {
    if (last.date < r.date) l[l.length - 1] = r;
  } else l.push(r);
  return l;
});

max_items.forEach(o => arr_of_obj[o.ord] = {
  emp_name: o.emp_name,
  date: o.date,
  max: true
});

console.log('max items', max_items);
console.log('updated array', arr_of_obj);

Creates a second array that only contains the max items, along with their original array index.

[ 
  { ord: 4, emp_name: 'Mark', date: 2018-05-06T07:00:00.000Z },
  { ord: 2, emp_name: 'John', date: 2018-04-05T07:00:00.000Z } 
]

Lastly iterate over it and update the array indexes in the original array. This preserves order of the original. I would also recommend breaking out the reduce function into a separate function for readability, but it works for this example.

Upvotes: 0

Abdulaziz Alaboudi
Abdulaziz Alaboudi

Reputation: 61

You can sort the array base on the date then mark the max. see my code

       let arr_of_obj = [{emp_name:'Mark',date:new Date('2018/05/01')},
                      {emp_name:'Mark',date:new Date('2018/05/02')},
                      {emp_name:'John',date:new Date('2018/04/05')},
                      {emp_name:'John',date:new Date('2018/03/22')},
                      {emp_name:'Mark',date:new Date('2018/05/06')}];

 let arr = arr_of_obj.slice().sort((a,b) => new Date(b.date) - new Date(a.date));

 let mark = arr[arr.findIndex(p => p.emp_name === 'Mark')];
 let john = arr[arr.findIndex(p => p.emp_name === 'John')];

 let new_array = arr_of_obj.map(obj => obj.date === mark.date || obj.date === john.date ? {...obj, max: true} : obj);

Upvotes: 1

Engineer
Engineer

Reputation: 48793

const arr = [{emp_name:'Mark',date:new Date('2018/05/01')},
              {emp_name:'Mark',date:new Date('2018/05/02')},
              {emp_name:'John',date:new Date('2018/04/05')},
              {emp_name:'John',date:new Date('2018/03/22')},
              {emp_name:'Mark',date:new Date('2018/05/06')}]

const max_map = {};   // Holds map of (name => obj_with_max_date) items, 
arr.forEach((item, i)=> {
    // Checking whether emp_name is not stored in map, then store the object 
    // and if `emp_name` is already exists in map, comparing `date` fields
    if (!max_map[item.emp_name] || max_map[item.emp_name].date < arr[i].date) {  
       max_map[item.emp_name] = arr[i];
    }
});

// Traversing the map and assigning flags for each emp_name
Object.keys(max_map).forEach( name => {
   max_map[name].max = true;
});

DEMO

Upvotes: 1

Related Questions