如何用更合适的lodash函数替换嵌套的foreach循环?

时间:2015-07-02 23:55:27

标签: javascript functional-programming lodash

我想提高我对函数式编程的了解,更具体地说是lodash的数据处理函数。我在下面汇总了一个合理的例子,我非常希望看到它有所不同,最好没有明确的forEach循环。

给出以下数据集:

// dateArray JSON
["2015-06-01T04:00:00.000Z", "2015-06-02T04:00:00.000Z", "2015-06-03T04:00:00.000Z"]

// projectList JSON
[{
    "_id": "53d487607464e4954927ba1c",
    "name": "Development"
}, {
    "_id": "540e104f7464e48d2f524560",
    "name": "My Aw&some Proj&ct"
}, {
    "_id": "52168d64839f153950000218",
    "name": "Internal Marketing"
}, {
    "_id": "5464e5787464e42e6df38da8",
    "name": "Communication"
}, {
    "_id": "NA",
    "name": "Not Assigned"
}]

// activeProjectList JSON
[{
    "date": "2015-6-1",
    "projects": [{
        "_id": "53d487607464e4954927ba1c",
        "h": 1
    }, {
        "_id": "NA",
        "h": 2.5
    }]
}, {
    "date": "2015-6-2",
    "projects": [{
        "_id": "540e104f7464e48d2f524560",
        "h": 1
    }, {
        "_id": "NA",
        "h": 2
    }]
}, {
    "date": "2015-6-3",
    "projects": [{
        "_id": "52168d64839f153950000218",
        "h": 1
    }, {
        "_id": "5464e5787464e42e6df38da8",
        "h": 3.25
    }, {
        "_id": "NA",
        "h": 0.5
    }]
}];

如何在避免使用foreach循环并支持更合适的lodash函数的情况下将其压缩到下面的结果中?

// series JSON (result)
[{
    "name": "Development",
    "data": [1, 0, 0]
}, {
    "name": "Not Assigned",
    "data": [2.5, 2, 0.5]
}, {
    "name": "My Aw&some Proj&ct",
    "data": [0, 1, 0]
}, {
    "name": "Internal Marketing",
    "data": [0, 0, 1]
}, {
    "name": "Communication",
    "data": [0, 0, 3.25]
}]

这是我目前最好的尝试:

_.map(activeProjectList, function (item) {

    item.date = new Date(item.date).toISOString();

    return item;
});

projectList = _.indexBy(projectList, '_id');

var projectTimes = {};

_.forEach(activeProjectList, function (item) {

    _.forEach(item.projects, function (subItem) {

        if (!projectTimes[subItem._id]) projectTimes[subItem._id] = {};

        projectTimes[subItem._id][item.date] = subItem.h;
    });
});

var series = [];
var seriesData;

_.forEach(projectTimes, function (item, key) {

    seriesData = [];

    _.forEach(dateArray, function (date) {

        if (item[date]) seriesData.push(item[date]);
        else seriesData.push(0);
    });

    series.push({
        name: projectList[key].name,
        data: seriesData
    });
});

这里是上述实现的小提琴:http://jsfiddle.net/8fe5oo49/

感谢您的时间。

1 个答案:

答案 0 :(得分:5)

不确定最终输出的顺序有多重要。对我来说,让项目列表以最初定义的顺序返回更有意义,但这可能不是你想要的那样

var series = _.map(projectList, function(project){
    return {
        'name': project.name,
        'data': _.map(dateArray, function(date){
             var p = _.findWhere(
                 _.find(activeProjectList, function(activeProj){
                    return new Date(activeProj.date).toISOString() == date
                }).projects, 
                {_id: project._id}
             )
             return (p ? p.h : 0) 
        })
    }
});

这将返回

[
    {"name":"Development","data":[1,0,0]},
    {"name":"My Aw&some Proj&ct","data":[0,1,0]},
    {"name":"Internal Marketing","data":[0,0,1]},
    {"name":"Communication","data":[0,0,3.25]},
    {"name":"Not Assigned","data":[2.5,2,0.5]}
]