-1

I have this object and I want to return a new object sorted by ascending date, taking into account the startTime that is a ISOString. (I'm also using moment) How can I do this?

const clinics = {
  "a0CW00000027OX3MAM": {
    "id": "a0CW00000027OX3MAM",
    "companyName": "Hendrick Medical Center",
    "startTime": "2018-08-10T05:30:00.000Z",
  },
  "a0CW00000026gjJMAQ": {
    "id": "a0CW00000026gjJMAQ",
    "companyName": "ABC Manufacturing",
    "startTime": "2018-08-10T10:36:00.000Z",
  },
  "a0CW00000026gipMAA": {
    "id": "a0CW00000026gipMAA",
    "companyName": "ABC Manufacturing",
    "startTime": "2018-08-01T10:36:00.000Z",
  }
}
Lizz Parody
  • 1,705
  • 11
  • 29
  • 48
  • Possible duplicate of [Sort with moment.js](https://stackoverflow.com/questions/48692757/sort-with-moment-js) – imjared Jul 30 '18 at 21:48
  • 1
    ISO strings have the benefit of ordering correctly when sorted as a string. Have you tried just sorting by the string value? – Heretic Monkey Jul 30 '18 at 21:49
  • Possible duplicate of [Jquery - Sort array by ISO 8601 date](https://stackoverflow.com/questions/12192491/jquery-sort-array-by-iso-8601-date) – Heretic Monkey Jul 30 '18 at 21:50
  • "*…a new object sorted by ascending date…*". You can't order the properties of an Object, they are unordered by specification. – RobG Jul 30 '18 at 23:41

2 Answers2

3

The following will sort the clinics by start time in ascending order.

const clinics = {
  "a0CW00000027OX3MAM": {
    "id": "a0CW00000027OX3MAM",
    "companyName": "Hendrick Medical Center",
    "startTime": "2018-08-10T05:30:00.000Z",
  },
  "a0CW00000026gjJMAQ": {
    "id": "a0CW00000026gjJMAQ",
    "companyName": "ABC Manufacturing",
    "startTime": "2018-08-10T10:36:00.000Z",
  },
  "a0CW00000026gipMAA": {
    "id": "a0CW00000026gipMAA",
    "companyName": "ABC Manufacturing",
    "startTime": "2018-08-01T10:36:00.000Z",
  }
};

const sorted = Object.values(clinics)
  .sort((a, b) => a.startTime > b.startTime)
  .reduce((m, c) => m.set(c.id, c), new Map());

for (let [key, value] of sorted.entries()) {
  console.log(key, value);
}

Edit - answer updated to use a Map, to guarantee property ordering.

fubar
  • 16,918
  • 4
  • 37
  • 43
  • 1
    You can't guarantee the order of object properties, they are unordered. – RobG Jul 30 '18 at 23:43
  • 1
    @RobG, cheers. I thought I'd read somewhere that `Object` property ordering was guaranteed in ES6+, but I seem to have been mistaken. I've updated my answer to use a `Map` instead. – fubar Jul 31 '18 at 00:03
2

Well your object isn't an array so you cant really sort it without converting it to an array first. Here is an example of converting it to an array and then sorting just using the text of the field because ISO will sort fine that way.

EDIT I updated it to add a function to convert it back to an object

const clinics = {
  "a0CW00000027OX3MAM": {
    "id": "a0CW00000027OX3MAM",
    "companyName": "Hendrick Medical Center",
    "startTime": "2018-08-10T05:30:00.000Z",
  },
  "a0CW00000026gjJMAQ": {
    "id": "a0CW00000026gjJMAQ",
    "companyName": "ABC Manufacturing",
    "startTime": "2018-08-10T10:36:00.000Z",
  },
  "a0CW00000026gipMAA": {
    "id": "a0CW00000026gipMAA",
    "companyName": "ABC Manufacturing",
    "startTime": "2018-08-01T10:36:00.000Z",
  }
}

function compare(a,b) {
  if (a.startTime < b.startTime)
     return -1;
  if (a.startTime > b.startTime)
    return 1;
  return 0;
}

function objectToArray(obj){
 var keys = Object.keys(obj);
  var ret = [];
  for (var i = 0; i < keys.length; i++)
   ret.push(obj[keys[i]]);
    
  return ret;
}

function arrayToObject(arr){
 var ret = {};
  for(var i = 0; i < arr.length; i++)
    ret[arr[i].id] = arr[i];
  return ret;
}

var arr = objectToArray(clinics);
console.log(arr.sort(compare));
console.log(arrayToObject(arr));
Adam H
  • 1,750
  • 1
  • 9
  • 24