【问题标题】:Sort a Javascript Object by Key, then by named property按键排序 Javascript 对象,然后按命名属性
【发布时间】:2017-06-18 03:08:46
【问题描述】:

我无法按 KEY (DESC) 对以下对象进行排序。 然后,按“notesList.id”属性 (DESC) 对每个项目进行排序。

预期顺序

  • “2017/04/17”
  • “2017/03/14”
  • “2017/02/30”

那么,对于“2017/04/17” notesList 项,这里是预期顺序

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

JS 对象

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"
      }
      ]
    }
  }
}

脚本

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

我错过了什么?非常感谢你

【问题讨论】:

  • 我认为您缺少的重要事情之一是对象未排序。与数组不同,您不能依赖它们以任何特定顺序排列,如果您需要顺序,则需要将它们存储为对象数组。相反,最好通过“键”查找对象。

标签: javascript arrays sorting javascript-objects


【解决方案1】:

我发现您的代码中有一些看起来不合适的地方。

  1. tmpArr.sort((a, b) => a > b ? a : b); 返回 tmpArr 的排序版本。它不会修改 myNotes 对象。
  2. Object.keys(myNotes.customNotes).sort(... 将返回来自 myNotes.customNotes 的对象数组,而不是像您预期的那样与 myNotes 具有相同结构的对象。
  3. 在上面的代码中,您没有对 notesList 进行排序。

假设你想得到一个数组,你只需要修复你的排序函数,并在 map 函数中对你的 notesList 进行排序。所以你的代码应该是这样的:

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

但是,如果你打算保留 myNotes 的结构,我建议你使用 reduce 函数。请参阅下面的代码:

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】:

您可以使用thenBy.js

这样

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

您还可以使用此库按属性名称排序

这样

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

【讨论】:

  • 嗨 Anik,这个 thenBy.js 库类似于我用过几次的一些排序库和函数,只有通过id 对我的对象的项目进行排序才会很有趣。但它似乎无法按它们的键(日期)对我的主要对象进行排序。
【解决方案3】:

您的sort 函数应返回零、正数或负数。您只是返回值。另请注意,这会将您的 customNotes 转换为数组,因为无法对对象进行排序。如果您不希望这种情况发生,您可以使用customNotes 中的键的排序数组维护另一个键,并使用该数组查找customNotes 中的值。另一种方法是使用新的Map 对象。 Map 支持排序键。

试试这个:

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)

【讨论】:

  • 请注意,返回值不必特别是 -1、1 或 0。它可以是任何负数、任何正数或 0。这在对数字进行排序时很有用(只需返回a - b).
  • 非常感谢:是的,我知道 Objects 是不可排序的,只有 Arrays 是可排序的。但是,@D-reaper 的答案非常紧凑,可以满足我当前的需求。我将您的结构保留在我身边以备将来需要,“以防万一”,因为使用 Javascript,您永远不知道有一天或另一天需要处理哪种类型的数据^!^ 非常感谢
猜你喜欢
  • 2010-11-24
  • 2019-12-03
  • 2011-07-24
相关资源
最近更新 更多