7

How to sort Javascript object of week days by weekdays i.e Here, is JSON format of object:

 {"Friday":["5:00pm to 12:00am"] ,"Wednesday":["5:00pm to 11:00pm"],"Sunday":["11:00am to 11:00pm"], "Thursday":["5:00pm to 11:00pm"],"Saturday":["11:00am to 12:00am"]}

where key is day i.e."Wednesday". I want to sort it based on order of weekdays i.e Sunday, Monday, Tuesday etc

Expected Output is:

{ "Wednesday":["5:00pm to 11:00pm"], "Thursday":["5:00pm to 11:00pm"], "Friday":["5:00pm to 12:00am"], "Saturday":["11:00am to 12:00am"], "Sunday":["11:00am to 11:00pm"]}

this is what i was trying.

var keys = {}; 
Object.keys(scope.daySpecificHours)
.map(function (k) { return [k, scope.daySpecificHours[k]]; })
.sort(function (a, b) {
if (a[0] < b[0]) return -1;
if (a[0] > b[0]) return 1;
return 0;
})
.forEach(function (d) {
scope.daySpecificHours[d[0]] = d;
});

Thanks.

Vishal Rajole
  • 1,329
  • 1
  • 12
  • 17
  • Can you post your code to show us what you've already tried, and explain what's wrong with it? – Reinstate Monica Cellio Dec 03 '15 at 13:02
  • I tried on console, but not able to complete it. – Vishal Rajole Dec 03 '15 at 13:05
  • 1
    Just to point you in the right direction. Moment.JS let's you provide an object like so and get the resulting day number `moment("Friday", "e").weekday()`. Combining this with something like lodash's `sortBy` could work pretty easily. Just a suggestion. – SlashmanX Dec 03 '15 at 13:05
  • @VishalRajole "I tried on console" is not posting your code that you need help with. Stack Overflow != Write my code for me. – Reinstate Monica Cellio Dec 03 '15 at 13:11
  • Updated my question. Please have a look. – Vishal Rajole Dec 03 '15 at 13:16
  • 1
    It's an object, you can't sort by properties name, order is not guaranteed in the specification: http://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order#5525820 – Shanoor Dec 03 '15 at 13:30
  • This is not duplicate! If we sort weekdays by considering them a text, then sort order would be wrong. http://stackoverflow.com/questions/1069666/sorting-javascript-object-by-property-value doesnot answer this question. – instinct Sep 02 '16 at 08:32

2 Answers2

29

Like I said in my comment, you can't sort an object but if you can change your data's format to have an array, you can easily sort it by using [].sort

let data = [
  { day: "Friday", hours: ["5:00pm to 12:00am"] },
  { day: "Wednesday", hours: ["5:00pm to 11:00pm"] },
  { day: "Sunday", hours: ["11:00am to 11:00pm"] },
  { day: "Thursday", hours: ["5:00pm to 11:00pm"] },
  { day: "Saturday", hours: ["11:00am to 12:00am"] }
];

const sorter = {
  // "sunday": 0, // << if sunday is first day of week
  "monday": 1,
  "tuesday": 2,
  "wednesday": 3,
  "thursday": 4,
  "friday": 5,
  "saturday": 6,
  "sunday": 7
}

data.sort(function sortByDay(a, b) {
  let day1 = a.day.toLowerCase();
  let day2 = b.day.toLowerCase();
  return sorter[day1] - sorter[day2];
});

console.log(data);
document.write("<pre>" + JSON.stringify(data, null, 3) + "</pre>");

edit

To "order" your object's keys by day of the week, again order is not guaranteed, use at your own risk

let data = {
  "Friday": ["5:00pm to 12:00am"],
  "Wednesday": ["5:00pm to 11:00pm"],
  "Sunday": ["11:00am to 11:00pm"],
  "Thursday": ["5:00pm to 11:00pm"],
  "Saturday": ["11:00am to 12:00am"]
};

const sorter = {
  "monday": 1,
  "tuesday": 2,
  "wednesday": 3,
  "thursday": 4,
  "friday": 5,
  "saturday": 6,
  "sunday": 7
};

let tmp = [];
Object.keys(data).forEach(function(key) {
  let value = data[key];
  let index = sorter[key.toLowerCase()];
  tmp[index] = {
    key: key,
    value: value
  };
});

let orderedData = {};
tmp.forEach(function(obj) {
  orderedData[obj.key] = obj.value;
});

console.log(orderedData);
document.write("<pre>" + JSON.stringify(orderedData, null, 3) + "</pre>");
Shanoor
  • 11,466
  • 2
  • 23
  • 37
  • Thanks. but I want to sort based on key names. Do check input object. – Vishal Rajole Dec 03 '15 at 15:12
  • I updated my answer but use the code at your own risk. – Shanoor Dec 03 '15 at 16:11
  • 1
    [According to MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort), the compare function should return a negative number, a positive number, or 0, not true or false. – intcreator Jun 21 '18 at 03:47
  • I've added an edit to update the function to return the values (if (sorter[day1] > sorter[day2]) return 1; if (sorter[day2] > sorter[day1]) return -1; return 0;) so that it will sort correctly. – Jobokai Apr 26 '19 at 13:23
2

Just as a proof of concept using ES6, this should work Requires MomentJS:

const unordered = {"Friday":["5:00pm to 12:00am"] ,"Wednesday":["5:00pm to 11:00pm"],"Sunday":["11:00am to 11:00pm"], "Thursday":["5:00pm to 11:00pm"],"Saturday":["11:00am to 12:00am"]};

const ordered = {};
Object.keys(unordered).sort(function (a, b) {
    return moment(a, 'ddd dddd').weekday() > moment(b, 'ddd dddd').weekday();
}).forEach(function(key) {
    ordered[key] = unordered[key];
});

console.log(ordered);

This returns:

{ 
    Sunday: [ '11:00am to 11:00pm' ],
    Wednesday: [ '5:00pm to 11:00pm' ],
    Thursday: [ '5:00pm to 11:00pm' ],
    Friday: [ '5:00pm to 12:00am' ],
    Saturday: [ '11:00am to 12:00am' ] 
}

Note: This is mainly a proof of concept to show it is possible, there are issues such as MomentJS treating Sunday as day 0 (based on user locale etc). You could easily write your own mapping of weekdays to int (Monday -> 0, Tuesday -> 1) and remove the MomentJS dependency.

EDIT: Expanding on above:

var days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']

Then change the sort function to

return days.indexOf(a) > days.indexOf(b)

const unordered = {"Friday":["5:00pm to 12:00am"] ,"Wednesday":["5:00pm to 11:00pm"],"Sunday":["11:00am to 11:00pm"], "Thursday":["5:00pm to 11:00pm"],"Saturday":["11:00am to 12:00am"]};

var days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']

const ordered = {};

Object.keys(unordered).sort(function (a, b) {
    return days.indexOf(a) > days.indexOf(b);
}).forEach(function(key) {
    ordered[key] = unordered[key];
});

console.log(ordered);

Example: http://www.es6fiddle.net/ihqg46kp/

SlashmanX
  • 2,278
  • 15
  • 16