将条目附加到嵌套数组

时间:2016-05-23 07:19:52

标签: javascript arrays json

基本上,我'试图得到一个如下所示的数组:

{
    "projects" : [{
        "project" : "Project One",
        "tasks" : [{
            "name" : "Task One"
        }, {
            "name" : "Task Two"
        }, {
            "name" : "Task Three"
        }]
    }, {
        "project" : "Project Two",
        "tasks" : [{
            "name" : "Task One"
        }, {
            "name" : "Task Two"
        }]
    }]
}

我目前有以下数组和一个脚本,它查看任务的每个元素并检查它是否已经不在项目名称列表中,然后插入第一个如果它不是,应该添加第二个元素,如果是的话,那就是我被困的地方:



var tasks = [{
        "name" : "Task One",
        "project" : "Project One"
    }, {
        "name" : "Task One",
        "project" : "Project Two"
    }, {
        "name" : "Task Two",
        "project" : "Project One"
    }, {
        "name" : "Task Three",
        "project" : "Project One"
    }, {
        "name" : "Task Two",
        "project" : "Project Two"
    }]


var projectNames = [];
var projects = [];
for ( i = 0; i < tasks.length; i++) {
    if (projectNames.indexOf(tasks[i].project) < 0) {
        // checks to see that it's not the projectNames list, and inserts the first entry
        projectNames.push(tasks[i].project);
        projects.push({
            project : tasks[i].project,
            tasks : {
                name : tasks[i].name
            }
        });
    } else {
        // if that project is already in the list, append the next entry
        var ind = projectNames.indexOf(tasks[i].project);
        projects[ind].tasks.push({
            name : tasks[i].name
        });
    }
}
&#13;
&#13;
&#13;

我的印象是projects[ind].tasks.push()无法使用,但我不确定用它替换它的正确方法是什么?

(同样,如果有更好的方法从第一个阵列到第二个阵列,我总是很乐意学习新的东西)

3 个答案:

答案 0 :(得分:2)

如果已经创建了相同的项目,则可以使用Array#forEach和thisArg对象。

var object = { "tasks": [{ "name": "Task One", "project": "Project One" }, { "name": "Task One", "project": "Project Two" }, { "name": "Task Two", "project": "Project One" }, { "name": "Task Three", "project": "Project One" }, { "name": "Task Two", "project": "Project Two" }] },
    result = { projects: [] };

object.tasks.forEach(function (a) {
    if (!this[a.project]) {
        this[a.project] = { project: a.project, task: [] };
        result.projects.push(this[a.project]);
    }
    this[a.project].task.push({ name: a.name });
}, Object.create(null));

console.log(result);

答案 1 :(得分:1)

你的问题在这里:

projects.push({ project: tasks[i].project, tasks: { name: tasks[i].name } });

您要将任务添加为对象,而不是数组。您应该将其添加为数组,并将对象作为唯一元素:

projects.push({ project: tasks[i].project, tasks: [{ name: tasks[i].name }] });

下面是一个替代解决方案,对于某些标准可能“更好”,但为了可维护性,我认为OP很好。我已经更改了任务的名称,以表明任务已分配给正确的项目。

var tasks = [{"name" : "Proj one, Task One", "project" : "Project One"},
             {"name" : "Proj two, Task One", "project" : "Project Two"},
             {"name" : "Proj one, Task Two", "project" : "Project One"},
             {"name" : "Proj one, Task Three", "project" : "Project One"},
             {"name" : "Proj two, Task Two", "project" : "Project Two"}
            ];

var projectNames = [];
var groupedTasks = tasks.reduce(function(acc, obj) {
                     var projectName = obj.project;
                     var idx = projectNames.indexOf(projectName);
                     if (idx == -1) {
                       projectNames.push(projectName);
                       idx = acc.projects.length;
                       acc.projects.push({project:projectName,tasks:[]});
                     }
                     acc.projects[idx].tasks.push({name:obj.name});
                     return acc;
                   }, {projects:[]});
                   
console.log(groupedTasks);

答案 2 :(得分:0)

由于这个问题已经有了正确的答案,我将在这里留下分组的功能,对您或将来通过此处的任何人都有用

&#13;
&#13;
 var tasks = {
     "tasks": [{
        "name": "Task One",
        "project": "Project One"
     }, {
        "name": "Task One",
        "project": "Project Two"
     }, {
        "name": "Task Two",
        "project": "Project One"
     }, {
        "name": "Task Three",
        "project": "Project One"
     }, {
        "name": "Task Two",
        "project": "Project Two"
     }]
  };

function groupBy(array, f_gb, f_content) {
    var groups = {};
    array.forEach(function(o) {
        var group = f_gb(o);
        groups[group] = groups[group] || [];
        if(f_content == null)
          groups[group].push(o);
        else
          groups[group].push(f_content(o));
    });
    return groups;
}

//An you call the group by like this:
var result = groupBy(tasks.tasks, 
    // function from what to filter from 
    function(item) {
        return item.project;
    }, 
    // optional: what to chose from the object filtered
    function(item){
        return { name : item.name};
    }
);

console.log(result);
&#13;
&#13;
&#13;