Tobías Matarasso
Tobías Matarasso

Reputation: 11

Sort array by one key that changes its form

I have the following problem. I have an array of activities that I have to sort by date. The problem is that the "date" key is not always the same. If it's a one day activity it looks like:

date: "2019-10-25T00:00:00.000Z"

But if it's two days or longer, it looks like:

date:{dateFrom: "2017-05-13T00:00:00.000Z", dateTo: "2017-05-14T00:00:00.000Z"}

I've tried a normal sorting or the type of function that sort two keys that are never null.

So, how could I sort this array by date?

activities = [{
        "date": {dateTo:"2019-05-20T00:00:00.000Z", dateFrom: "not important"},
        activity: 5
    },{
        "date": {dateTo:"2019-05-05T00:00:00.000Z", dateFrom: "not important"},
        activity: 2
    },{
        "date": "2019-05-10T00:00:00.000Z",
        activity: 3
    },{
        "date": "2019-05-25T00:00:00.000Z",
        activity: 6
    },{
        "date": "2019-05-01T00:00:00.000Z",
        activity: 1
    },{
        "date": "2019-05-15T00:00:00.000Z",
        activity: 4
}]

Upvotes: 1

Views: 76

Answers (4)

ossiggy
ossiggy

Reputation: 219

const newActivities = activities.map((act) => {
  const { activity, date } = act;
  if(typeof date === 'string'){
    return { date: Date.parse(date), activity }
   }
 return { date: Date.parse(date.dateTo), activity}
})

  newActivties.sort((a,b) => a - b)

Upvotes: 0

zmag
zmag

Reputation: 8241

Check date property whether it has dateTo property or not and sort it with its value.

const activities = [{
  "date": {
    dateTo: "2019-05-20T00:00:00.000Z",
    dateFrom: "not important"
  },
  activity: 5
}, {
  "date": {
    dateTo: "2019-05-05T00:00:00.000Z",
    dateFrom: "not important"
  },
  activity: 2
}, {
  "date": "2019-05-10T00:00:00.000Z",
  activity: 3
}, {
  "date": "2019-05-25T00:00:00.000Z",
  activity: 6
}, {
  "date": "2019-05-01T00:00:00.000Z",
  activity: 1
}, {
  "date": "2019-05-15T00:00:00.000Z",
  activity: 4
}]

activities.sort((a, b) => {
  const x = a.date.dateTo || a.date
  const y = b.date.dateTo || b.date

  if (x > y) return 1
  if (x < y) return -1
  return 0
})

console.log(activities)

Upvotes: 0

Dacre Denny
Dacre Denny

Reputation: 30360

One solution would be to define a helper function like getItemDate(), combined with the regular Array#sort() method to achieve what you require:

const activities = [{
        "date": {dateTo:"2019-05-20T00:00:00.000Z", dateFrom: "not important"},
        activity: 5
    },{
        "date": {dateTo:"2019-05-05T00:00:00.000Z", dateFrom: "not important"},
        activity: 2
    },{
        "date": "2019-05-10T00:00:00.000Z",
        activity: 3
    },{
        "date": "2019-05-25T00:00:00.000Z",
        activity: 6
    },{
        "date": "2019-05-01T00:00:00.000Z",
        activity: 1
    },{
        "date": "2019-05-15T00:00:00.000Z",
        activity: 4
}];

/* Define helper function that obtains a date timestamp from activities list item. If
date key is an object, item.date.dateTo is used, otherwise item.date is used */
function getItemDate(item) {

  let date = (typeof item.date === 'object') ? item.date.dateTo : item.date;
  
  return Date.parse(date);
}

/* Use helper function to sort items in activities list */
activities.sort((a,b) => getItemDate(a) - getItemDate(b))

console.log(activities)

Upvotes: 1

Jan
Jan

Reputation: 2853

You can use the sort-method of arrays and do a custom comparison. Inside the compare-function you can get the date-string from the two objects and convert it to a timestamp with the help of Date.parse. After that you have to compare these timestamps and return the sorting-rule (-1, 1 or 0).

let activities = [{
        "date": {dateTo:"2019-05-20T00:00:00.000Z", dateFrom: "not important"},
        activity: 5
    },{
        "date": {dateTo:"2019-05-05T00:00:00.000Z", dateFrom: "not important"},
        activity: 2
    },{
        "date": "2019-05-10T00:00:00.000Z",
        activity: 3
    },{
        "date": "2019-05-25T00:00:00.000Z",
        activity: 6
    },{
        "date": "2019-05-01T00:00:00.000Z",
        activity: 1
    },{
        "date": "2019-05-15T00:00:00.000Z",
        activity: 4
}];

function compare( a, b ) {
  let aDateString = a.date.dateTo ? a.date.dateTo : a.date;
  let bDateString = b.date.dateTo ? b.date.dateTo : b.date;
  let aDate = Date.parse(aDateString);
  let bDate = Date.parse(bDateString);
  if ( aDate < bDate ){
    return -1;
  }
  if ( aDate > bDate ){
    return 1;
  }
  return 0;
}
activities.sort( compare );

console.log(activities);

Upvotes: 0

Related Questions