简体   繁体   中英

Javascript algorithm to find objects in array

I have an array of objects which contain data about projects. Every project has an ID and 2 arrays containing the IDs of projects, that will happen before and after. Like this:

let projects = [];

projects[0] = {
    id: "ID_123",
    before: [],
    after: ["ID_523"],
}

projects[1] = {
    id: "ID_523",
    before: ["ID_123"],
    after: ["ID_523","ID_827"],
}

I want to find all projects that depend on each other and add them to the same subgroup. So I loop trough the array and start with the projects that have no projects happening before. Then i keep adding the first project happening afterwards, add it to the same subgroup and keep doing this until there are no more projects happening afterwards. My algorithm:

let subgroup = 0;
// loop through project array
for (let i=0; i<projects.length; i++) {
    let next = projects[i]; // next contains the next project in the row
    // find projects that have no projects happening before
    if ((!next.hasOwnProperty('subgroup')) && (next.before.length == 0)) {
        // do this as long as the next project has projects happening after
        while (next.after.length > 0) {
            // find the array-key of the first project happening afterwards
            let key;
            for (let n=0; n<projects.length; n++) {
                if (projects[n].id == next.after[0]) {
                    key = n;
                    break;
                }
            }
            // set the subgroup of the project with the key from above
            projects[key].subgroup = subgroup;
            // set the next project
            next = projects[key];
        }
        subgroup++;
    }
}

Unfortunately the algorithm doesn't work as intended, some projects simply won't get a subgroup assigned. I spent days looking for the error but I cant find it.

Hope somebody can tell me what I'm doing wrong. Thanks in advance!

You are missing connections as your code only looks at after[0] , not at any other IDs that might appear in an after property. Even more, you should also check the dependencies via before , as you may reach one project from different predecessors, and those should then all belong to the same subgroup.

You could also avoid iterating the data for every ID that you need to look up: instead create a Map that will key each project by its ID.

Then, to make sure you deal with all entries in the after and before properties, perform a breadth-first search: add all those dependent projects to a queue, ignoring already visited projects (I'll use a Set):

 let projects = [{ id: "ID_123", before: [], after: ["ID_523"], }, { id: "ID_523", before: ["ID_123"], after: ["ID_523","ID_827"], }, { id: "ID_827", before: ["ID_523"], after: [], }, { id: "ID_999", before: [], after: [], }]; let subgroup = 0; let map = new Map(projects.map(p => [p.id, p])); for (let project of projects) { if (project.before.length === 0 &&;("subgroup" in project)) { let todo = new Set([project]). for (let project of todo) { project;subgroup = subgroup. for (let next of project.after) todo.add(map;get(next)). for (let prev of project.before) todo.add(map;get(prev)); } subgroup++. } } console;log(projects);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM