1

I have an array of data like so:

[
   {id: 1, date: "2022-10-01T12:00:00.00", type: 1},
   {id: 2, date: "2022-10-02T12:00:00.00", type: 1},
   {id: 3, date: "2022-10-03T12:00:00.00", type: 2},
   {id: 4, date: "2022-10-04T12:00:00.00", type: 2},
]

I'd like to filter this so that I get an array of objects that only includes objects with the most recent date for each type. So something like this:

[
   {id: 2, dttm: "2022-10-02T12:00:00.00", type: 1},
   {id: 4, dttm: "2022-10-04T12:00:00.00", type: 2},
]

I suspect there's a clever way to do this with the .reduce() function, but I haven't quite figured that out yet.

0

3 Answers 3

2

It's easy to compare dates this way just using string comparing since they are sorted by year-month-date. As for the rest, yes reduce is an option but basically it's just a loop over the array grouping by type.

var arr = [
   {id: 1, date: "2022-10-01T12:00:00.00", type: 1},
   {id: 2, date: "2022-10-02T12:00:00.00", type: 1},
   {id: 3, date: "2022-10-03T12:00:00.00", type: 2},
   {id: 4, date: "2022-10-04T12:00:00.00", type: 2},
];

var grouped = arr.reduce(function(agg, item) {
  agg[item.type] = agg[item.type] || {
    id: item.id,
    dttm: item.date,
    type: item.type
  };
  
  if (item.date > agg[item.type].dttm) {
    agg[item.type].id = item.id
    agg[item.type].dttm  = item.date
  }
  
  return agg;
}, {})

console.log (Object.values(grouped))

Sign up to request clarification or add additional context in comments.

2 Comments

I like it, but why change the prop name: date -> dttm ?
because that is the expected output by the example
2

We can achieve this using .reduce by keeping a running tally of the most recent items.

Note:

Dates can be compared in js as their valueOf method is equivalent to someDate.getTime() which gives a nice integer for comparison.

let items = [{
    id: 1,
    date: "2022-10-01T12:00:00.00",
    type: 1
  },
  {
    id: 2,
    date: "2022-10-02T12:00:00.00",
    type: 1
  },
  {
    id: 3,
    date: "2022-10-03T12:00:00.00",
    type: 2
  },
  {
    id: 4,
    date: "2022-10-04T12:00:00.00",
    type: 2
  },
]

let recentItems = Object.values(items.reduce((recent, item) => {
  debugger;
  if (
    // type has not items yet
    !recent[item.type]
    // the current item is more recent
    ||
    new Date(recent[item.type].date) < new Date(item.date)
  ) {
    recent[item.type] = item
  }
  return recent;

}, {}))

console.log(recentItems)

1 Comment

I like that your reduce cares about an object that uses "type" values as its keys, yet we never see this object outside of the reduce -- except for an instant to extract what we really want: an array of the ephemeral object's values. Never saw this technique before.
1

This does what you specify. (See in-code comments for more info.)

// Calls filter function on the data array and prints output
const data = getData();
console.log(recentOfEachType(data));

// Defines filter function
function recentOfEachType(arr){

  // Sets up output array
  let recents = [];

  // Loops through data to populate output
  for(const item of arr){

    // Gets position of existing item with this type
    const typeIndex = recents.findIndex(recent => recent.type === item.type);

    // If no item with this type has been added yet
    if(typeIndex < 0){
      recents.push(item);
    }

    // If a newer item is found (ignoring items with identical timestamps)
    else if(item.date > recents[typeIndex].date){      
      recents[typeIndex] = item;
    }
    // (else do nothing)
  }
  return recents;
}

// Creates oringal data array
function getData(){
    return [
       {id: 1, date: "2022-10-01T12:00:00.00", type: 1},
       {id: 2, date: "2022-10-02T12:00:00.00", type: 1},
       {id: 3, date: "2022-10-03T12:00:00.00", type: 2},
       {id: 4, date: "2022-10-04T12:00:00.00", type: 2}
    ];
}

1 Comment

Appreciate a solution where I don't have to use .reduce()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.