2

I need to get all unique days of multiple date values in the format DD.MM.. In this example data, there are two values for the 24th of december:

const data = [
    { date: ISODate("2019-12-24T03:24:00Z") },
    { date: ISODate("2019-12-24T04:56:00Z") },
    { date: ISODate("2019-12-25T02:34:00Z") },
    { date: ISODate("2019-12-26T01:23:00Z") }
]

So the result should be

const result = [
    '24.12.',
    '25.12.',
    '26.12.'
]

So first of all I'll map my data and split the values only for the dates:

const dates = data.map(d => d.date.toString().split('T')[0])

But how do I get the unique values and change the output format?


Update

I came up with this, but it looks very complicated...

data.map(d => {
  const dateSplit = d.date.toString().split('T')[0].split('-')
  return dateSplit[2] + '.' + dateSplit[1] + '.'
})
.filter((value, index, self) {
  return self.indexOf(value) === index
})
2
  • 1
    Where is ISODate coming from? Is that a library or a class you made? Commented Dec 27, 2019 at 0:19
  • 1
    @mwilson It comes from mongoDB query result Commented Dec 27, 2019 at 0:20

5 Answers 5

5

It seems that ISODate returns a standard JS Date object. You can use Date.getDate() to get the day, and Date.getMonth() to get the month (0 based, so we need to add 1):

const data = [
  { date: new Date('2019-12-24T03:24:00Z') },
  { date: new Date('2019-12-24T04:56:00Z') },
  { date: new Date('2019-12-25T02:34:00Z') },
  { date: new Date('2019-12-26T01:23:00Z') }
]

const result = [...new Set(data.map(({ date: d }) => 
  `${d.getDate()}.${d.getMonth() + 1}.`
))]

console.log(result)

Previous answer:

Use a regular expression to match the month and the day, and assign them to consts using destructuring. Assemble the string using template literal. Remove duplicates by assigning the values to a Set, and then spreading back to an array.

Note: Since I don't have access to the ISODate, I've removed it. I left .toString() although it's not needed in this example, but will be needed when used with ISODate.

const data = [
  { date: '2019-12-24T03:24:00Z' },
  { date: '2019-12-24T04:56:00Z' },
  { date: '2019-12-25T02:34:00Z' },
  { date: '2019-12-26T01:23:00Z' }
]

const pattern = /-([0-9]{2})-([0-9]{2})T/

const result = [...new Set(data.map(d => {
  const [, mon, day] = d.date.toString().match(pattern)
  
  return `${day}.${mon}.`;
}))]

console.log(result)

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

Comments

0

Use .filter() to filter through only values that are the first of their value.

//temporary function
const ISODate = (d) => d;

const data = [{
    date: ISODate("2019-12-24T03:24:00Z")
  },
  {
    date: ISODate("2019-12-24T04:56:00Z")
  },
  {
    date: ISODate("2019-12-25T02:34:00Z")
  },
  {
    date: ISODate("2019-12-26T01:23:00Z")
  }
]

const dates = data.map(d => d.date.toString().split('T')[0].split("-").slice(1, 3).reverse().join(".") + ".")

console.log(dates.filter((v, i, a) => a.indexOf(v) === i));

Comments

0

You can do this pretty easily by using Array.reduce. Note that I converted ISODate to be Date since I don't have that class, but it should be the same concept.

const data = [
    { date: new Date("2019-12-24T03:24:00Z") },
    { date: new Date("2019-12-24T04:56:00Z") },
    { date: new Date("2019-12-25T02:34:00Z") },
    { date: new Date("2019-12-26T01:23:00Z") }
];
const result = data.reduce( (acc, curr) => {
  if (acc.length > 0) {
    const hasDate = acc.find(d => d.date.getMonth() === curr.date.getMonth() && d.date.getDate() === curr.date.getDate());
    if (!hasDate) { acc.push(curr); }
  } else {
    acc.push(curr);
  }
  return acc;
}, []);

console.log(result);

Comments

-1

I would use the uniq function in the Underscore.js library:

const data = [
    { date: ISODate("2019-12-24T03:24:00Z") },
    { date: ISODate("2019-12-24T04:56:00Z") },
    { date: ISODate("2019-12-25T02:34:00Z") },
    { date: ISODate("2019-12-26T01:23:00Z") }
];

let dates = _.uniq(data.map(d => d.date.toString().split('T')[0]));

3 Comments

But how do I get the expected result (changed format)?
I disagree. Importing an entire library just to get a unique array is too much. You can write a function in a couple lines of code to do this. Why would you import thousands of lines of code when you're only going to use a single function? Array.reduce is your friend here.
@mwilson: Yes, importing Underscore just for this one function would be overkill, I agree. But it is a useful library to have around if you find yourself doing a lot of this kind of data manipulation. There are also alternatives such as lodash which have most of the functionality of Underscore but aren't as heavy.
-1

A nice considerable way is:

const array = [1, 2, 6, 5,5, 5, 3, 7, 8];

const uniqueKeys = array.reduce((hashMap, value) => {
  if (!hashMap[value]) {
    hashMap[value] = true;
  }
  return hashMap;
}, {});

const uniqueValues = Object.keys(uniqueKeys);

console.log(uniqueValues);

It is nice because it iterates the array once, instead of x * x (a.k.a log(n) instead of log(n^2) as with .filter() example

const array = [1, 2, 6, 5,5, 5, 3, 7, 8];

const uniqueKeys = array.reduce((hashMap, value) => {
  if (!hashMap[value]) {
    hashMap[value] = true;
  }
  return hashMap;
}, {});

const uniqueValues = Object.keys(uniqueKeys);

console.log(uniqueValues);

Comments

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.