【问题标题】:Is there a more efficient way to sort an Array in an Array in an Object?有没有更有效的方法来对对象中的数组中的数组进行排序?
【发布时间】:2019-02-04 21:07:57
【问题描述】:

对于下面的array-object-thing结构:

Events : {
    events : [
        {
          startDTG : {day: 0, month: 0, year: 0, time: "" },
          endDTG : {day: 0, month: 0, year: 0, time: "" },
          mode: ""
        },
        ...
    ],
    blah...,
    blah...,
    blah...
}

我正在努力寻找一种更有效的方法来根据 startDTG 键(日期时间组)对 events 对象进行排序。目前我使用以下方法,但我觉得必须有更好的方法来做到这一点!

SortEvents: function() {
    this.Events.events.sort(function(a, b){return a.startDTG.time - b.startDTG.time});
    this.Events.events.sort(function(a, b){return a.startDTG.day - b.startDTG.day});
    this.Events.events.sort(function(a, b){return a.startDTG.month - b.startDTG.month});
    this.Events.events.sort(function(a, b){return a.startDTG.year - b.startDTG.year});
},

编辑1:愿望是按Year > Month > Day > Time排序

我正处于一个关键点,我要以效率的名义放弃这个定制的 DTG。如果需要,我可以发布整个代码,但可能没有完全意义,因为它是 JS 编写的,可以在名为“Medialon”的专有控制系统中工作

编辑 2:在下方添加了一个快速制作的 JSON 代码转储,以帮助提高结构的可读性。忽略它们都是“字符串”的事实,这就是 Medialon 如何为持久性字符串化

{
  "events": [
    {
      "startDTG": {
        "day": "8",
        "month": "2",
        "year": "2019",
        "time": "06:35",
        "dayName": "5"
      },
      "endDTG": {
        "day": "9",
        "month": "2",
        "year": "2019",
        "time": "08:35",
        "dayName": "6"
      },
      "mode": "1"
    },
    {
      "startDTG": {
        "day": "27",
        "month": "2",
        "year": "2019",
        "time": "17:35",
        "dayName": "3"
      },
      "endDTG": {
        "day": "28",
        "month": "2",
        "year": "2019",
        "time": "06:35",
        "dayName": "4"
      },
      "mode": "1"
    },
    {
      "startDTG": {
        "day": "1",
        "month": "2",
        "year": "2019",
        "time": "14:35",
        "dayName": "5"
      },
      "endDTG": {
        "day": "2",
        "month": "2",
        "year": "2019",
        "time": "12:35",
        "dayName": "6"
      },
      "mode": "1"
    }
  ],

【问题讨论】:

  • 在上面,你最终得到的只是按year排序的事件。因此,一种更有效的方法是不进行其他排序.. :) 我假设您希望按year 然后month,然后day 然后time 进行排序,但这不是你做的方式复合排序。
  • 你能清理一下代码示例吗?很难分辨什么是数组,什么是对象。我认为您缺少一些{}...
  • 您可以用||分隔排序标准,即this.Events.events.sort(function(a, b){return a.startDTG.year- b.startDTG.year || a.startDTG.month- b.startDTG.month || ... //etc})
  • @Keith:因为现在几乎所有的排序实现都是稳定的,这将满足我们的期望:首先按年排序,然后按月排序,然后按天排序。 (时间作为字符串更成问题)。不过,这绝对不是最有效的。
  • @ScottSauyet Edge 没有稳定的排序,如果这是一个问题,Chrome 直到最近也没有。而且 ES7 并没有声明稳定的排序是必需的,所以我会非常小心地依赖这种行为。

标签: javascript arrays sorting object controls


【解决方案1】:

我还是不太确定你的数据结构,但应该是这样的:

const events = [
  {name: 'a', startDTG: {year: 2019, month: 1,  day: 4,  time: '14:21:46'}, endDTG: ''},
  {name: 'b', startDTG: {year: 2018, month: 10, day: 7,  time: '12:13:59'}, endDTG: ''},
  {name: 'c', startDTG: {year: 2019, month: 1,  day: 4,  time: '09:23:51'}, endDTG: ''},
  {name: 'd', startDTG: {year: 2019, month: 1,  day: 2,  time: '15:02:36'}, endDTG: ''},
  {name: 'e', startDTG: {year: 2017, month: 9,  day: 17, time: '03:25:29'}, endDTG: ''},
  {name: 'f', startDTG: {year: 2017, month: 9,  day: 17, time: '03:25:28'}, endDTG: ''},
  {name: 'g', startDTG: {year: 2018, month: 4,  day: 14, time: '11:07:42'}, endDTG: ''},
]

events.sort((
  {startDTG: {year: y1, month: m1, day: d1, time: t1}}, 
  {startDTG: {year: y2, month: m2, day: d2, time: t2}}
) => 
  // y1 - y2 || m1 - m2 || d1 - d2 || (t1 < t2 ? -1 : t1 > t2 ? 1 : 0)           
  y1 - y2 || m1 - m2 || d1 - d2 || t1.localeCompare(t2)
)

console.log(events)

【讨论】:

  • 是的,这样好多了。我想知道localeCompare 是否比三元更容易阅读。
  • @MarkMeyer:是的,这肯定看起来更好。
  • @MarkMeyer OP提到高效,所以可能正在寻找最快的。 Tenery 应该更快,而快速的基准测试会使 localeCompare 慢 70% 左右。
  • 好吧,它们都可供 OP 选择。无论哪种方式,这应该比执行四个单独的排序要快很多。
  • @ScottSauyet 所以为了让 JS 在这个程序中工作,我必须做一些讨价还价的事情。对于您在 .sort() 之后所做的别名部分,它的技术名称是什么,所以我可以进一步阅读它。尽管看起来很有希望,但它并不能作为一个片段中的一滴使用!
【解决方案2】:

另一种解决方案是将您的数据映射到Date(),然后将返回的毫秒数与getTime() 进行比较。

let data = {
  "events": [
    {
      "startDTG": {"day": "8", "month": "2", "year": "2019", "time": "6:35", "dayName": "5"},
      "endDTG": {"day": "9", "month": "2", "year": "2019", "time": "6:35", "dayName": "6"},
      "mode": "1"
    },
    {
      "startDTG": {"day": "27", "month": "2", "year": "2019", "time": "6:35", "dayName": "3"},
      "endDTG": {"day": "28", "month": "2", "year": "2019", "time": "6:35", "dayName": "4"},
      "mode": "1"
    },
    {
      "startDTG": {"day": "1", "month": "2", "year": "2019", "time": "6:35", "dayName": "5"},
      "endDTG": {"day": "2", "month": "2", "year": "2019", "time": "6:35", "dayName": "6"},
      "mode": "1"
    }
  ]
};

const startDTGToStr = o => `${o.year}-${o.month}-${o.day} ${o.time}`

data.events.sort((a, b) =>
{
    a = new Date(startDTGToStr(a.startDTG));
    b = new Date(startDTGToStr(b.startDTG));
    return a.getTime() - b.getTime();
});

console.log(data.events);

【讨论】:

  • 虽然这将比对数组进行 4 次排序要快,但为每次比较创建一个 Date 对象会产生一些开销。因此,它比像下面显示的@Scott 那样进行复合比较要慢。但是,如果 OP 首先存储了 DateTime,这将是可行的方法。
猜你喜欢
  • 2015-10-30
  • 1970-01-01
  • 2022-01-18
相关资源
最近更新 更多