如何在js中创建按日期分组的json?

时间:2018-10-31 11:29:15

标签: javascript lodash

我有一个按日期排序的对象数组:

const alerts = [{ 
    id: 1, date: '2018-10-31T23:18:31.000Z', name: 'Joke', title: 'this is the first 1' 
}, { 
    id: 2, date: '2018-10-30T23:18:31.000Z', name: 'Mark', title: 'this is the second one' 
}]

我正在尝试按日期对警报进行“分组”,因此尝试创建具有日期标题的“ datesections”,其结果应类似于:

const sections = [{
   date: '2018-10-31T23:18:31.000Z',
   heading: 'today',
   alerts: [{ id: 1, date: '2018-10-31T23:18:31.000Z', name: 'Joke', 
   title: 'this is the first one' }]
}, {
   date: '2018-10-30T23:18:31.000Z',
   heading: 'Yesterday',
   alerts: [{ id: 2, date: '2018-05-30T23:18:31.000Z', name: 'Mark', 
   title: 'this is the second one' }]
}]

我尝试了一些操作,但是无法弄清楚如何在警报属性中获取具有相同日期的警报:

const sections2=alerts.map(a =>
    ({
        date: a.date,
        heading:'today new',
        alerts:alerts
    })
)

4 个答案:

答案 0 :(得分:2)

const alerts = [
    { id: 1, date: '2018-10-31T23:18:31.000Z', name: 'Joke', title: 'this is the first 1' },
    { id: 2, date: '2018-05-30T23:18:31.000Z', name: 'Mark', title: 'this is the second one' }
]

const grouping = _.groupBy(alerts, element => element.date.substring(0, 10))
const sections = _.map(grouping, (items, date) => ({
  date: date,
  alerts: items
}));

console.log(sections);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

无法帮助您处理标题-如果既不是“今天”也不是“昨天”怎么办?

答案 1 :(得分:0)

我觉得您在这里要问几件事。关键是如何按日期将日期分组。

为此,您首先需要知道如何分组。 This answer可能会有所帮助。

就如何按天分组,有很多方法可以做到这一点。我想到的最简单的方法是,截断日期字符串中“ T”之后的所有内容并对其进行排序。

答案 2 :(得分:0)

您可以使用正则表达式匹配所需日期的一部分,然后对数据进行分组。您可以在此处添加所需的标题。希望这会有所帮助。

const alerts = [
    { id: 1, date: '2018-10-31T23:18:31.000Z', name: 'Joke', title: 'this is the first 1' },
    { id: 2, date: '2018-10-30T23:18:31.000Z', name: 'Mark', title: 'this is the second one' },
    { id: 3, date: '2018-10-30T23:14:32.000Z', name: 'Mark', title: 'this is the third one' }
];

const groupByDate = (data) => {

    return data.reduce((acc, val) => {

        const date = val.date.match(/\d{4}-\d{2}-\d{2}/g).toString();

        const item = acc.find((item) => item.date.match(new RegExp(date, 'g')));

        if (!item) acc.push({ date: val.date, alerts: [val], heading: 'some heading' });

        else item.alerts.push(val);

        return acc;

    }, []);
};

console.log(groupByDate(alerts));

答案 3 :(得分:0)

也许您需要这样的东西?没有太多时间,最后一次数组解析可以更优雅的方式完成;)

var alerts = [
    { id: 1, date: '2018-10-31T23:18:31.000Z', name: 'Joke', title: 'this is the first 1' },
    { id: 3, date: '2018-10-31T23:44:31.000Z', name: 'Joke1', title: 'this is the 2nd' },
    { id: 2, date: '2018-10-30T23:18:31.000Z', name: 'Mark', title: 'this is the second one' },
    { id: 4, date: '2018-10-30T23:45:31.000Z', name: 'Mark1', title: 'this is the 3rd' },
    { id: 5, date: '2018-10-27T23:18:31.000Z', name: 'Mark2', title: 'this is the 4th' },
];

var processedAlerts = [], finalAlerts;

(function(initAlerts){
    //iterate through array to make keys to group by day
    for(var i = 0; i < initAlerts.length; i++){
        processedAlerts[i] = initAlerts[i];
        //substring here can be more sophisticated - this was faster
        initAlerts[i].keyDate = initAlerts[i].date.substr(0, 10);
    }

    //supporting function to convert string to date
    //to acheve more detailed sorting that includes time
    //just use date object and use hours, minutes and/or seconds to create Date object
    function dateFromString(strDate){
        var date, tmpDate;

        //convert string to array - I assume that date format is always the same
        //yyyy-mm-dd and will become Array 0: year, 1: month, 2: day of the month
        tmpDate = strDate.split("-");

        //moths in js are zero pased so Jan is 0, Feb is 1 and so on
        //so we want to substract 1 from human readable month value to get correct date
        date = new Date(tmpDate[0], tmpDate[1]-1, tmpDate[2]);

        return date;
    }

    //function used to compare dates and passed to sort function
    function comparedates(obj1, obj2){
        var date1, date2;

        date1 = dateFromString(obj1.keyDate);
        date2 = dateFromString(obj2.keyDate);

        let comparison = 0;

        if(date1>date2){
            comparison = 1;
        } else if(date1<date2){
            comparison = -1;
        }

        //to achieve reverse just multiply comparison result by -1
        return comparison*(-1);
    }

    function getHeader(date){
        //here place logic to generate header
        //this involves comparing dates probably from keyDate

        return "temp header: " + date.toString()
    }

    //sort the array by keyDate from newest to oldest
    processedAlerts.sort(comparedates);

    //final array rebuild
    //pass here sorted array
    finalAlerts = (function(arrayAlerts){
        var aAlerts = [], k = 0;

        for(var j = 0; j < arrayAlerts.length; j++){
            //check if entry for date exists
            //if no than create it
            if(!aAlerts[k]){
                aAlerts[k] = {
                    //removed title because I asummed that each alert has unique title and put them in alerts instead
                    date: arrayAlerts[j].keyDate, //agroupped date
                    heading: getHeader(arrayAlerts[j].keyDate), //update this function to return personalized heading
                    //here you can shape the alert object how you need
                    //I just passed it as it was
                    alerts: [arrayAlerts[j]] //array with first object inside
                };
            } else {
                //add another alert to day
                aAlerts[k].alerts.push(arrayAlerts[j]) //array with first object inside
            }

            //increasing final array key
            //if there is previous entry and keys are the same for current and previous
            if(arrayAlerts[j-1] && (arrayAlerts[j].keyDate == arrayAlerts[j-1].keyDate)){
                k++;
            }
        }

        return aAlerts;

    })(processedAlerts);

})(alerts);

console.log(finalAlerts);