使用javascript创建累积对象

时间:2018-12-11 03:57:21

标签: javascript arrays sorting date for-loop

我有一个日期数组和一个对象数组。每个都有一个date属性。我需要按日期累计排序对象。因此,对于date数组中的每个日期,我想使用其date属性早于date数组中日期的每个对象创建一个累积对象。

例如,以下日期数组和对象数组:

{
  "rules": {
    "meetups": {
      "$meetupId": {
        ".read": "auth.uid != null",
        ".write": "auth.uid != null"
      }
    }
  }
}

所需的输出为:

['2017-11-5', '2018-3-1', '2018-3-22']

[{name: 'Jes', date: '2017-11-2'}, {name: 'Jill', date: '2018-1-5'}, {name: 'Joe', date: '2018-2-25'}, {name: 'Jack', date: '2018-3-21'}]

我正在尝试使用大约500个日期和30,000个对象来执行此操作。

这是当前的代码段,但是由于要迭代的对象数量众多,所以我在性能方面遇到了问题。

[{name: 'Jes', date: '2017-11-2'}]

[{name: 'Jes', date: '2017-11-2'}, {name: 'Jill', date: '2018-1-5'}, {name: 'Joe', date: '2018-2-25'}]

[{name: 'Jes', date: '2017-11-2'}, {name: 'Jill', date: '2018-1-5'}, {name: 'Joe', date: '2018-2-25'}, {name: 'Jack', date: '2018-3-21'}]

2 个答案:

答案 0 :(得分:2)

您可以filter()遍历日期,因为每个日期都需要一个结果数组。然后,您可以在地图上根据日期{{3}}来创建该数组的人:

let dates = ['2017-11-5', '2018-3-1', '2018-3-22']

let people = [{name: 'Jes', date: '2017-11-2'}, {name: 'Jill', date: '2018-1-5'}, {name: 'Joe', date: '2018-2-25'}, {name: 'Jack', date: '2018-3-21'}]

let cumul = dates.map(d => people.filter(person => person.date <= d))
console.log(JSON.stringify(cumul, null, 2))

答案 1 :(得分:0)

有几种方法可以改善算法,同时将关联索引保留在enter image description here中:

  • 预先计算日期对象,并且对于peopledates都只计算一次。
  • 以升序排列dates
  • 重新使用预先计算/预先过滤的结果,请参见Dynamic Programming
  • 保存datespeople索引以保持原始顺序
  • 如果remaining,则在lastChunkremaining之间交换项目以减小people[i].date < dates[j]的大小

算法代码:

function filter(dates, people){
    let lastChunk = [];
    let remaining = people;
    let results = [];
    // precalculate dates, preserve indexes and sort by date
    let sortedDates = dates
        .map((value, index) => {
            return {
                date: new Date(value),
                index: index
            };
        })
        .sort((a, b) => {
            return a.date<b.date?-1:a.date==b.date?0:1;
        });
    let peopleWithDates = people.map((value, index) => {
        value.dateObject = new Date(value.date);
        value.index = index;
        return value;
    });
    for(const i in sortedDates){
        const comp = sortedDates[i].date
        remaining = remaining.filter((value, index) => {
            if(value.dateObject<=comp){
                let itemIndex = value.index;
                delete value.dateObject;
                delete value.index;
                lastChunk.splice(itemIndex, 0, value);
                return false;
            }else{
                return true;
            }
        });
        results[sortedDates[i].index] = [...lastChunk];
    }
    return results;
}