Sort a Javascript Object by Key, then by named pro

2019-09-22 07:41发布

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

3条回答
我只想做你的唯一
2楼-- · 2019-09-22 07:52

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);

查看更多
Anthone
3楼-- · 2019-09-22 08:09

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)

查看更多
放荡不羁爱自由
4楼-- · 2019-09-22 08:10

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")
);
查看更多
登录 后发表回答