基本上,我'试图得到一个如下所示的数组:
{
"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;
我的印象是projects[ind].tasks.push()
无法使用,但我不确定用它替换它的正确方法是什么?
(同样,如果有更好的方法从第一个阵列到第二个阵列,我总是很乐意学习新的东西)
答案 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)
由于这个问题已经有了正确的答案,我将在这里留下分组的功能,对您或将来通过此处的任何人都有用
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;