JSON minor data remover

Viewed 58

I have a JSON, who has two people with the same names, but the start date is different, I would like to leave only the larger one

        {
            "startDate": "2020-11-01",
            "name":"Gustavo Fran"
        },
        {
            "startDate": "2020-10-01",
            "name":"Gustavo Fran"
        },
        {
            "startDate": "2020-10-01",
            "name":"Henry Fran"
        }
3 Answers

const data = [{ "startDate": "2020-11-01", "name":"Gustavo Fran" }, { "startDate": "2020-10-01", "name":"Gustavo Fran" }, { "startDate": "2020-10-01", "name":"Henry Fran" }];

const res = [...
  // iterate over the list
  data.reduce((map, item) => {
    const { name, startDate } = item;
    // get previous map value with name if exists
    const prev = map.get(name);
    // if not found, or this one has a greater startDate, update the map
    if(!prev || Date.parse(startDate) > Date.parse(prev.startDate))
      map.set(name, item);
    return map;
  }, new Map)
  // return name items with greatest start dates
  .values()
];

console.log(res);

You could use Array.prototype.reduce() like this:

const input = [
  {
    startDate: "2020-11-01",
    name: "Gustavo Fran",
  },
  {
    startDate: "2020-10-01",
    name: "Gustavo Fran",
  },
  {
    startDate: "2020-10-01",
    name: "Henry Fran",
  },
];

const result = input.reduce((acc, cur) => {
  const found = acc.find((x) => x.name === cur.name);
  if (found && new Date(found.startDate) < new Date(cur.startDate)) {
    found.startDate = cur.startDate;
    return acc;
  } else {
    return [...acc, cur];
  }
}, []);

console.log(result);

You can use reduce to iterate over the array and create a new array of unique items. If there are duplicate names, keep only the most recent.

Given the dates are in ISO 8601 format, they can be compared as strings without parsing to Date objects. The following implements the above, and if a newer duplicate is found, it replaces the current duplicate in the accumulator.

let data = [
  {
    "startDate": "2020-11-01",
    "name": "Gustavo Fran"
  },
  {
    "startDate": "2020-10-01",
    "name": "Gustavo Fran"
  }, {
    "startDate": "2020-10-01",
    "name": "Henry Fran"
  }
];
  
let list = data.reduce((acc, obj) => {
  // Look for a duplicate
  let idx = acc.findIndex(el => el.name == obj.name);
  // If there isn't one, add it to the accumulator
  // Otherwise, replace the current one with obj if it's newer
  idx == -1? acc.push(obj) :
         obj.startDate > acc[idx].startDate? acc.splice(idx, 1, obj) : null;
  return acc;
}, []);

console.log(list);

I think the above is efficient as it doesn't parse timestamps to Dates and doesn't create additional (and redundant) maps or arrays. It would be more efficient if it also kept an index to items in the accumulator based on name, so the item could just be looked up to get its index rather than using findIndex.

Related