Daniel R.
Daniel R.

Reputation: 649

Javascript's method forEach() creates array with undefined keys

I am building a simple todo app, and I'm trying to get the assigned users for each task. But let's say that in my database, for some reason, the tasks id starts at 80, instead of starting at 1, and I have 5 tasks in total.

I wrote the following code to get the relationship between user and task, so I would expect that at the end it should return an array containing 5 keys, each key containing an array with the assigned users id to the specific task.

Problem is that I get an array with 85 keys in total, and the first 80 keys are undefined.

I've tried using .map() instead of .forEach() but I get the same result.

let assignedUsers = new Array();

this.taskLists.forEach(taskList => {
    taskList.tasks.forEach(task => {
        let taskId = task.id;
        assignedUsers[taskId] = [];

        task.users.forEach(user => {
            if(taskId == user.pivot.task_id) {
                assignedUsers[taskId].push(user.pivot.user_id);
            }
        });
    });
});

return assignedUsers;

I assume the issue is at this line, but I don't understand why...

assignedUsers[taskId] = [];

I managed to filter and remove the empty keys from the array using the line below:

assignedUsers = assignedUsers.filter(e => e);

Still, I want to understand why this is happening and if there's any way I could avoid it from happening.

Looking forward to your comments!

Upvotes: 0

Views: 67

Answers (3)

Akxe
Akxe

Reputation: 11585

This should work as you want it to. It also uses more of JS features for the sake of readability.

return this.taskLists.reduce((acc, taskList) => {
    taskList.tasks.forEach(task => {
        const taskId = task.id;
        acc[taskId] = task.users.filter(user => taskId == user.pivot.task_id);
    });
    return acc;
}, []);

But you would probably want to use an object as the array would have "holes" between 0 and all unused indexes.

Upvotes: 1

WilliamNHarvey
WilliamNHarvey

Reputation: 2485

Your keys are task.id, so if there are undefined keys they must be from an undefined task id. Just skip if task id is falsey. If you expect the task id to possibly be 0, you can make a more specific check for typeof taskId === undefined

this.taskLists.forEach(taskList => {
    taskList.tasks.forEach(task => {
        let taskId = task.id;
        // Skip this task if it doesn't have a defined id
        if(!taskId) return;
        assignedUsers[taskId] = [];

        task.users.forEach(user => {
            if(taskId == user.pivot.task_id) {
                assignedUsers[taskId].push(user.pivot.user_id);
            }
        });
    });
});

Upvotes: 0

Kai Lehmann
Kai Lehmann

Reputation: 508

If your taskId is not a Number or autoconvertable to a Number, you have to use a Object. assignedUsers = {};

Upvotes: 4

Related Questions