Sort a Javascript Object by Key, then by named property

天涯浪子 提交于 2019-12-13 09:17:18

问题


I am having trouble into sorting the following Object by KEY (DESC). Then, sorting each item by the "notesList.id" property (DESC).

Expected order

  • "2017/04/17"
  • "2017/03/14"
  • "2017/02/30"

Then, for the "2017/04/17" notesList items, here is the Expected order :

  • id:57
  • id:48
  • id:12

The JS Object

var myNotes = {
  "customNotes":{
    "2017/04/17":{
      "concernedDate":"2017/04/17",
      "notesList":[
        {
          "id":48,
          "title":"Title 48"
        },
        {
          "id":12,
          "title":"Title 12"
        },
        {
          "id":57,
          "title":"Title 57"
        }
      ]
    },
    "2017/02/30":{
      "concernedDate":"2017/02/30",
      "notesList":[
      {
        "id":92,
        "title":"Title 92"
      }
      ]
    },
    "2017/03/14":{
      "concernedDate":"2017/03/14",
      "notesList":[
      {
        "id":92,
        "title":"Title 92"
      }
      ]
    }
  }
}

The Script

//Convert the OBJECT to an ARRAY
var tmpArr = Object.keys(myNotes.customNotes);

//Sort (Not working)
tmpArr.sort((a, b) => a > b ? a : b);

//Convert back the ARRAY to an OBJECT
Object.keys(myNotes.customNotes).sort((a, b) => a > b ? a : b).map(k => myNotes.customNotes[k]);

What am I missing ? I thank you very much


回答1:


I observe a few things that seem out of place in your code.

  1. tmpArr.sort((a, b) => a > b ? a : b); returns a sorted version of tmpArr. it will not modify myNotes object.
  2. Object.keys(myNotes.customNotes).sort(... will return an array of objects from myNotes.customNotes, and not an object that has the same structure as myNotes like you intended.
  3. In the code above, you are not sorting notesList.

Suppose you want to to get an array, all you need is to fix your sort function and also sort your notesList in the map function. So your code should look like this:

var myNotes={customNotes:{"2017/04/17":{concernedDate:"2017/04/17",notesList:[{id:48,title:"Title 48"},{id:12,title:"Title 12"},{id:57,title:"Title 57"}]},"2017/02/30":{concernedDate:"2017/02/30",notesList:[{id:92,title:"Title 92"}]},"2017/03/14":{concernedDate:"2017/03/14",notesList:[{id:92,title:"Title 92"}]}}};

var res = Object.keys(myNotes.customNotes)
  .sort((a, b) => a < b)
  .map(k => {   
    let currNote = myNotes.customNotes[k];
    currNote.notesList.sort((a, b) => a.id < b.id)
    return myNotes.customNotes[k];
});

console.log(res);

But, if you intend to keep the structure of myNotes, I would suggest that you use reduce function. See my code below:

var myNotes={customNotes:{"2017/04/17":{concernedDate:"2017/04/17",notesList:[{id:48,title:"Title 48"},{id:12,title:"Title 12"},{id:57,title:"Title 57"}]},"2017/02/30":{concernedDate:"2017/02/30",notesList:[{id:92,title:"Title 92"}]},"2017/03/14":{concernedDate:"2017/03/14",notesList:[{id:92,title:"Title 92"}]}}};

// MY SOLUTION
var sortedNotes = Object.keys(myNotes.customNotes)
  .sort((a, b) => a < b)
  .reduce((acc, val, _, arr) => { 
    acc[val] = myNotes.customNotes[val];
    acc[val].notesList.sort((a, b) => a.id < b.id);
    return acc;  
},{});

console.log(sortedNotes);



回答2:


You can use thenBy.js

Like this

data.sort(
    firstBy(function (v1, v2) { return v1.name.length - v2.name.length; })
    .thenBy(function (v1, v2) { return v1.population - v2.population; })
    .thenBy(function (v1, v2) { return v1.id - v2.id; })
);

You can also sort by property name by using this library

Like this

data.sort(
    firstBy(function (v) { return v.name.length; })
    .thenBy("population")
    .thenBy("id")
);



回答3:


Your sort function should return either zero, a positive number or a negative number. You are just returning the values. Also note that this will convert your customNotes into an array, since objects cannot be sorted. If you do not wish that to happen, you can maintain another key with a sorted array of the keys in customNotes and use this array to look up the values in customNotes. Another approach would be to use the new Map object. Map supports sorted keys.

Try this:

var myNotes = {
  "customNotes":{
    "2017/04/17":{
      "concernedDate":"2017/04/17",
      "notesList":[
        {
          "id":48,
          "title":"Title 48"
        },
        {
          "id":12,
          "title":"Title 12"
        },
        {
          "id":57,
          "title":"Title 57"
        }
      ]
    },
    "2017/02/30":{
      "concernedDate":"2017/02/30",
      "notesList":[
      {
        "id":92,
        "title":"Title 92"
      }
      ]
    },
    "2017/03/14":{
      "concernedDate":"2017/03/14",
      "notesList":[
      {
        "id":92,
        "title":"Title 92"
      }
      ]
    }
  }
}

var myNewNotes = {};
myNewNotes.customNotes = Object.keys(myNotes.customNotes).sort((a, b) => {
  if (a < b) return -1
  else if (a > b) return 1;
  else return 0;
}).map(key => sorted(myNotes.customNotes[key]));

function sorted(note) {
  note.notesList = note.notesList.sort((a, b) => {
    if (a.id < b.id) return -1;
    else if (a.id > b.id) return 1;
    else return 0;
  })
  return note;
}

console.log(myNewNotes)


来源:https://stackoverflow.com/questions/44611392/sort-a-javascript-object-by-key-then-by-named-property

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!