2

I would like to refine my knowledge of functional programming, more specifically lodash's data crunching functions. I put together a reasonable example below and I would very much like to see it done differently, preferably without explicit forEach loops.

Given the following data sets:

// 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
    }]
}];

How would you crunch it into the result below while avoiding foreach loops and favoring more appropriate lodash functions?

// 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]
}]

This is my best attempt at the moment:

_.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
    });
});

Here's a fiddle with the above implementation: http://jsfiddle.net/8fe5oo49/

Thank you for your time.

1 Answer 1

5

Not sure how important the order of the final output is. For me it made more sense to have the project list returned in the same order it was originally defined but this might not be what you were looking for

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) 
        })
    }
});

This will return

[
    {"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]}
]
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the prompt response. The order does not matter and this is exactly what I was looking for. Just out of curiosity, how would you modify this solution if "projectList JSON" contained projects that are not necessarily present in the "activeProjectList JSON". In order words, projects that have no "active" project data to associate with, should be eliminated from the final output.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.