【问题标题】:Flatten and sort nested array of object by its array value按其数组值展平和排序嵌套的对象数组
【发布时间】:2021-06-29 00:08:54
【问题描述】:
// My data is like this
const data = [
  { 
    id: 1,
    color: "red",
    time: [ 
     { start: new Date("2021-4-3"), end: new Date("2021-4-4") }, 
     { start: new Date("2021-4-2"), end: new Date("2021-4-3") }
    ]
  },
  {
    id: 2,
    color: "blue",
    time: [ 
     { start: new Date("2021-4-2"), end: new Date("2021-4-3") }
    ]
  }
]

我想对时间进行排序,然后像下面这样调整数据。

[
  { id: "1-0", start: new Date("2021-4-2"), end: new Date("2021-4-3"), color: "red" },
  { id: "1-1", start: new Date("2021-4-3"), end: new Date("2021-4-4"), color: "red" },
  { id: "2-0", start: new Date("2021-4-2"), end: new Date("2021-4-3"), color: "blue" },
]

我想知道有没有更好的算法来处理这种情况?下面是我的尝试。 (我也尝试了 ES6 语法 reduceflatMapflat,但我找不到更好的方法来处理这种情况。)

let arr = [];
let timeLength = 0;
for (let i = 0; i < data.length; i++) {
  timeLength = data[i].time.length;
  if (timeLength !== 1) {
    data[i].time.sort((a, b) => new Date(a.start) - new Date(b.start)); // sort time
  }
  for (let j = 0; j < timeLength; j++) {
    arr.push({
      id: data[i].id + "-" + i,
      color: data[i].color,
      start: data[i].time[j].start,
      end: data[i].time[j].end,
    });
  }
}

【问题讨论】:

  • 我已经回答了,但现在我意识到您正在寻找一个更好的解决方案...您的解决方案不起作用吗?
  • 这段代码是可行的,但我只是想弄清楚如何提高这段代码的性能。顺便说一句,我也运行你的代码@Nick,它会像 js bench 中的 25% 性能一样下降,但是你的代码非常整洁,感谢你的分享。 ;)
  • 复杂度最高的步骤是对时间列表进行排序。除非你能找到一种不用排序的方法来做到这一点,否则我认为性能不会有很大的提高。
  • @AbhinavMathur,你能解释一下,如果我可以通过使用 db 或 sql 忽略排序时间,你认为最好的答案是什么?通过使用递归算法什么的?
  • @PoWenChen 你的迭代方法更好,因为递归只会增加递归开销

标签: javascript arrays algorithm performance


【解决方案1】:

我看到你的代码中有一个明显的减速:在sort 调用中,你重复调用new Date(...)。没有理由这样做。您的字段已经是日期,因此您可以按原样使用它们。我更喜欢使用flatMapmap,所以我的版本应该是这样的:

const convert = (data) =>
  data .flatMap (
    ({time, ...rest}) => [...time] .sort ((a, b) => a .start - b .start) 
                                   .map (t => ({...rest, ...t}))
  )

const data = [{id: 1, color: "red", time: [{start: new Date("2021-4-3"), end: new Date("2021-4-4")}, {start: new Date("2021-4-2"), end: new Date("2021-4-3")}]}, {id: 2, color: "blue", time: [{start: new Date("2021-4-2"), end: new Date("2021-4-3")}]}]

console .log (convert (data))
.as-console-wrapper {max-height: 100% !important; top: 0}

如果您使用 ISO 格式的字符串而不是 Date 对象,例如 2021-04-03,您也可以直接排序,无需任何 Date 实例化:

   [...time] .sort (({start: s1}, {start: s2}) => s1 < s2 ? -1 : s1 > s2 ? 1 : 0)

如果您的输入对象完全没有用处,您可以跳过time 的浅层克隆,将[...time] .sort (...) 替换为time .sort (...)。但这不会有太大的收获,而且您的原始数据的变异可能会有问题。

【讨论】:

  • 哇,你真的做到了。您在 js 基准测试中的答案比我的解决方案快 50%。
猜你喜欢
  • 2021-05-14
  • 1970-01-01
  • 2020-07-12
  • 1970-01-01
  • 1970-01-01
  • 2021-03-22
  • 1970-01-01
  • 2015-11-06
  • 2021-10-20
相关资源
最近更新 更多