Reputation: 9084
I am having an array ,
var data = [
{ id: 1, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2017-05-01]" },
{ id: 2, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2018-01-01]" },
{ id: 3, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2019-01-01]" },
{ id: 4, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2017-05-01]" },
{ id: 5, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2018-01-01]" },
{ id: 6, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2019-01-01]" },
{ id: 7, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2018-01-01]" },
{ id: 8, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2019-01-01]" },
{ id: 9, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2017-05-01]" }
];
data.forEach(function(result) {
console.log(result.jobCategoryWithFromDate);
});
which gives the above result in console..
Here inside the foreach, i need to return the jobCategoryWithFromDate
that has the latest date.
So expected result is, (same like below)..
ASSIST.. / Assistance [valid from 2019-01-01]
PROF.. / Professional [valid from 2019-01-01]
SEN.. / Senior [valid from 2019-01-01]
The above is the expected result and no change in it, just need to filter the result and return jobCategoryWithFromDate
returns unique value with latest date..
Despite of the duplicate names, the filter needs to be handled based on the date (latest)..
Edit:
I have already accepted answer but later only i came to know that it is not working in all scenario, I am sorry for not testing it completely..
Don't know whether my explanation gone wrong, but thing is if the user name is same then filter needs to be done based on date or otherwise unique user with any date needs to be displayed.
Eg:
var data = [
{ id: 1, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2017-05-01]" },
{ id: 2, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2018-01-01]" },
{ id: 3, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2019-01-01]" },
{ id: 4, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2017-05-01]" },
{ id: 5, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2018-01-01]" },
{ id: 6, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2019-01-01]" },
{ id: 7, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2018-01-01]" },
{ id: 8, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2019-01-01]" },
{ id: 9, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2017-05-01]" },
{ id: 10, jobCategoryWithFromDate: "Jun.. / Junior [valid from 2018-01-01]" },
{ id: 11, jobCategoryWithFromDate: "Usr.. / User [valid from 2019-01-01]" },
{ id: 12, jobCategoryWithFromDate: "Man.. / Manager [valid from 2017-05-01]" }
];
function extractDate(string){
return string.match(/[0-9]+-[0-9]+-[0-9]+/g);
}
var result = data.reduce((newestDates, currentItem)=>{
if (newestDates.length===0) newestDates.push(currentItem);
else {
const dateDifference = new Date(extractDate(newestDates[0].jobCategoryWithFromDate)) - new Date(extractDate(currentItem.jobCategoryWithFromDate));
if (dateDifference===0) newestDates.push(currentItem); // push items with the same date as newest found
else if (dateDifference <= 0) newestDates = [currentItem]; // if item has newer date the original array gets replaced with one containing just this item
// ignore case dateDifference >= 0 because we do not need to do anything with dates older than the newest found
}
return newestDates;
},[]);
console.log(result);
Here in this snippet look at the last three values, which have different username but same date with previous records..
Here expected result is i need to get all the last three records along with above three, because they are different user, like
ASSIST.. / Assistance [valid from 2019-01-01]
PROF.. / Professional [valid from 2019-01-01]
SEN.. / Senior [valid from 2019-01-01]
Jun.. / Junior [valid from 2018-01-01]
Usr.. / User [valid from 2019-01-01]
Man.. / Manager [valid from 2017-05-01]
Upvotes: 1
Views: 346
Reputation: 6714
Assuming that the date is in format YYYY-MM-DD
you can just extract part of the string containing date from each element and create date object from it
EDIT: it seems that what you wanted was to get the last date for every user instead of just getting an array of entries with the latest dates, edited snippet to match it (you can edit part of regex extracting the name if you want a different comparison distinguishing between users)
var data = [
{ id: 1, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2017-05-01]" },
{ id: 2, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2018-01-01]" },
{ id: 3, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2019-01-01]" },
{ id: 4, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2017-05-01]" },
{ id: 5, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2018-01-01]" },
{ id: 6, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2019-01-01]" },
{ id: 7, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2018-01-01]" },
{ id: 8, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2019-01-01]" },
{ id: 9, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2017-05-01]" },
{ id: 10, jobCategoryWithFromDate: "Jun.. / Junior [valid from 2018-01-01]" },
{ id: 11, jobCategoryWithFromDate: "Usr.. / User [valid from 2019-01-01]" },
{ id: 12, jobCategoryWithFromDate: "Man.. / Manager [valid from 2017-05-01]" }
];
function extractNameNDate(string){
return [string.match(/^\w+/), string.match(/[0-9]+-[0-9]+-[0-9]+/g)];
}
var result = data.reduce((newestDates, currentItem)=>{
const [user, date] = extractNameNDate(currentItem.jobCategoryWithFromDate);
if (newestDates[user]) {
// compare dates for given user
const [storedUser, storedDate] = extractNameNDate(newestDates[user].jobCategoryWithFromDate);
const dateDifference = new Date(storedDate) - new Date(date);
if (dateDifference <= 0) newestDates[user] = currentItem;
} else {
newestDates[user]=currentItem;
}
return newestDates;
},{});
result = Object.values(result);
console.log(result);
Here is an edited version to match entire first part of the string till the []
braces
var data = [
{ id: 1, jobCategoryWithFromDate: "01-05 Data Specialist [valid from 2019-01-01]" },
{ id: 2, jobCategoryWithFromDate: "01-05 Support [valid from 2019-01-01]" },
{ id: 3, jobCategoryWithFromDate: "03-04 Technician [valid from 2019-01-01]" },
{ id: 4, jobCategoryWithFromDate: "05 Engineer [valid from 2019-01-01]" },
{ id: 5, jobCategoryWithFromDate: "05 Technician [valid from 2019-01-01]" },
{ id: 6, jobCategoryWithFromDate: "05 Technologist [valid from 2019-01-01]" },
{ id: 7, jobCategoryWithFromDate: "06 Engineer [valid from 2019-01-01]" },
{ id: 8, jobCategoryWithFromDate: "06-07 Sr. Technician [valid from 2019-01-01]" },
{ id: 9, jobCategoryWithFromDate: "Intern [valid from 2019-01-01]" },
{ id: 10, jobCategoryWithFromDate: "06-07 Support [valid from 2019-01-01]" },
{ id: 11, jobCategoryWithFromDate: "06-07 Technologist [valid from 2019-01-01]" },
{ id: 12, jobCategoryWithFromDate: "07 Engineer [valid from 2019-01-01]" },
{ id: 13, jobCategoryWithFromDate: "08 Senior [valid from 2019-01-01]" },
{ id: 14, jobCategoryWithFromDate: "08-09 Support [valid from 2019-01-01]" },
{ id: 15, jobCategoryWithFromDate: "09 Senior [valid from 2019-01-01]" },
{ id: 16, jobCategoryWithFromDate: "10-11 Principal [valid from 2019-01-01]" },
{ id: 17, jobCategoryWithFromDate: "12-13 Sr. Principal [valid from 2019-01-01]" },
{ id: 18, jobCategoryWithFromDate: "14 Vice President [valid from 2019-01-01]" },
{ id: 19, jobCategoryWithFromDate: "15 President [valid from 2019-01-01]" }
];
function extractNameNDate(string){
return [string.match(/[^\/]*/), string.match(/[0-9]+-[0-9]+-[0-9]+/g)];
}
var result = data.reduce((newestDates, currentItem)=>{
const [user, date] = extractNameNDate(currentItem.jobCategoryWithFromDate);
if (newestDates[user]) {
// compare dates for given user
const [storedUser, storedDate] = extractNameNDate(newestDates[user].jobCategoryWithFromDate);
const dateDifference = new Date(storedDate) - new Date(date);
if (dateDifference <= 0) newestDates[user] = currentItem;
} else {
newestDates[user]=currentItem;
}
return newestDates;
},{});
result = Object.values(result);
console.log(result);
Upvotes: 1
Reputation: 1167
I would find the latest date first and then filter the array for objects with this date. This will return only the objects with the highest date:
var data = [
{ id: 1, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2017-05-01]" },
{ id: 2, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2018-01-01]" },
{ id: 3, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2019-01-01]" },
{ id: 4, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2017-05-01]" },
{ id: 5, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2018-01-01]" },
{ id: 6, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2019-01-01]" },
{ id: 7, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2018-01-01]" },
{ id: 8, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2019-01-01]" },
{ id: 9, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2017-05-01]" }
];
/* Add new property to data objects to store the "valid from" timestamp - Avoids parsing the text twice */
data.forEach(function(element, index, array) {
var dateText = element.jobCategoryWithFromDate.match(/\[valid from (\d{4}-\d{2}-\d{2})\]$/)[1];
array[index].fromDateTimestamp = +(new Date(dateText));
});
/* Get the highest value (the latest date) */
var max = data.reduce(function(currentMax, value) {
return Math.max(currentMax, value.fromDateTimestamp);
}, 0);
/* Filter the data array to only include objects with the latest date */
var newData = data.filter(function(value) {
return value.fromDateTimestamp === max;
});
console.log(newData);
Upvotes: 1
Reputation: 6446
You could just use a simple sort by extracting the date with regex, then use a recursive function to check if there are multiple dates the same:
var data = [
{ id: 1, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2017-05-01]" },
{ id: 2, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2018-01-01]" },
{ id: 3, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2019-01-01]" },
{ id: 4, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2017-05-01]" },
{ id: 5, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2018-01-01]" },
{ id: 6, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2019-01-01]" },
{ id: 7, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2018-01-01]" },
{ id: 8, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2019-01-01]" },
{ id: 9, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2017-05-01]" }
];
const getDate = date => +date.match(/[0-9]{4}-[0-9]{2}-[0-9]{2}/g)[0].split('-').join('')
data = data.sort(({jobCategoryWithFromDate:date1}, {jobCategoryWithFromDate:date2}) => getDate(date2) - getDate(date1))
const getRecent = (data, i=0) => getDate(data[i].jobCategoryWithFromDate) === getDate(data[i + 1].jobCategoryWithFromDate) ? [data[i], ...getRecent(data, i+1)] : [data[i]]
getRecent(data).forEach(obj => console.log(obj))
Upvotes: 0
Reputation: 114
You can do it using a simple reduce, You could improve the reduce by storing the array and also the currentMaxDateTS instead of recalculate the timestamp in every iteration.
Don't hesitate if you need more explanation around this code snippet
const data = [
{ id: 1, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2017-05-01]" },
{ id: 2, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2018-01-01]" },
{ id: 3, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2019-01-01]" },
{ id: 4, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2017-05-01]" },
{ id: 5, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2018-01-01]" },
{ id: 6, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2019-01-01]" },
{ id: 7, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2018-01-01]" },
{ id: 8, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2019-01-01]" },
{ id: 9, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2017-05-01]" }
];
// Function returning the date string inside [valid from 2017-05-01]
const getDateFromJobCategory = (jobCategoryWithFromDate) => jobCategoryWithFromDate.match(/[0-9]+-[0-9]+-[0-9]+/g);
const filteredData = data.reduce((acc, data) => {
// Get data date in timestamp
const dataDateString = getDateFromJobCategory(data.jobCategoryWithFromDate);
const dataDateTS = new Date(dataDateString).getTime();
// Get current max date in timestamp
const currentMaxDate = getDateFromJobCategory(acc[0]);
const currentMaxDateTS = new Date(currentMaxDate).getTime()
return dataDateTS > currentMaxDateTS ? [data.jobCategoryWithFromDate] : dataDateTS === currentMaxDateTS ? [...acc, data.jobCategoryWithFromDate] : acc
}, ["[valid from 0001-01-01]"]);
const finalResult = filteredData.forEach(jobCategoryWithFromDate =>
console.log(jobCategoryWithFromDate))
Upvotes: 0
Reputation: 1901
you can apply regex to extract the date from string jobCategoryWithFromDate
. then sort by date, you will get latest results on top.
var data = [
{ id: 1, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2017-05-01]" },
{ id: 2, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2018-01-01]" },
{ id: 3, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2019-01-01]" },
{ id: 4, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2017-05-01]" },
{ id: 5, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2018-01-01]" },
{ id: 6, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2019-01-01]" },
{ id: 7, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2018-01-01]" },
{ id: 8, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2019-01-01]" },
{ id: 9, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2017-05-01]" }
];
var result= data.map(d => ({...d, date: d.jobCategoryWithFromDate.match(/(\d{1,4}([.\-/])\d{1,2}([.\-/])\d{1,4})/g)[0]}))..sort((a, b)=> new Date(b.date) - new Date(a.date))
console.log(result)
Upvotes: 0