Javascript检查嵌套数组结构中的对象属性

时间:2017-11-30 15:50:06

标签: javascript arrays

我在这里处理两个主要对象。一个叫做tasks,它是一个对象数组。另一个名为userSelectedRoles,它是角色ID的数组。

在我的tasks数组中,有一个名为Roles的属性,它也是一个对象数组。

我正在尝试查看任何任务中是否存在userSelectedRoles,如果没有,请将其添加到任务中。

我创造了一些伪装,我试图绕过它。

示例:

var userSelectedRoles = [1, 2, 3],
  tasks = [{
    TaskName: 'Task 1',
    TaskID: 1,
    Roles: [{
      RoleName: 'Role1',
      RoleID: 1
    }, {
      RoleName: 'Role 2',
      RoleID: 2
    }]
  }, {
    TaskName: 'Task 2',
    TaskID: 2,
    Roles: [{
      RoleName: 'Role1',
      RoleID: 1
    }, {
      RoleName: 'Role 3',
      RoleID: 3
    }]
  }]


// Loop over our tasks
for (var t = 0; t < tasks.length; t++) {

  // Loop over the roles
  for (var r = 0; r < tasks[t].Roles.length; r++) {

    // Loop over our user selected roles
    for (var sr = 0; sr < userSelectedRoles.length; sr++) {

      // If this user selected role exists within our roles, continue
      if (tasks[t].Roles[r].RoleID == userSelectedRoles[sr]) {
        // This role exists, no need to do anything
      } else {
        // This user selected role does not exist in our tasks, we need to add it
        tasks[t].Roles.push({
          RoleName: 'Blah',
          RoleID: userSelectedRoles[sr]
        })
      }
    }

  }
}

上面的代码无法正常工作,我的小提琴撞坏了,所以我假设某个地方出现了循环错误。

有没有更容易的方法来做到这一点,而不必做所有的循环?

这里的最终目标是在两个任务中添加一个新角色。 Task 1 = Role 3&amp; Task 2 = Role 2

思想?

3 个答案:

答案 0 :(得分:0)

您可以使用哈希表并收集ID。然后迭代userSelectedRoles,如果没有设置,则将对象推送到Roles

&#13;
&#13;
var userSelectedRoles = [1, 2, 3],
    tasks = [{ TaskName: 'Task 1', TaskID: 1, Roles: [{ RoleName: 'Role1', RoleID: 1 }, { RoleName: 'Role 2', RoleID: 2 }] }, { TaskName: 'Task 2', TaskID: 2, Roles: [{ RoleName: 'Role1', RoleID: 1 }, { RoleName: 'Role 3', RoleID: 3 }] }];

tasks.forEach(function (task) {
    var roleIds = Object.create(null);
    task.Roles.forEach(function (role) {
        roleIds[role.RoleID] = true;
    });
    userSelectedRoles.forEach(function (id) {
        if (!roleIds[id]) {
            task.Roles.push({ RoleName: 'Blah', RoleID: id });
        }
    });
});

console.log(tasks);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;

ES6与Set

&#13;
&#13;
var userSelectedRoles = [1, 2, 3],
    tasks = [{ TaskName: 'Task 1', TaskID: 1, Roles: [{ RoleName: 'Role1', RoleID: 1 }, { RoleName: 'Role 2', RoleID: 2 }] }, { TaskName: 'Task 2', TaskID: 2, Roles: [{ RoleName: 'Role1', RoleID: 1 }, { RoleName: 'Role 3', RoleID: 3 }] }];

tasks.forEach(function (task) {
    var ids = new Set(task.Roles.map(({ RoleID }) => RoleID));
    userSelectedRoles.forEach(id => ids.has(id) || task.Roles.push({ RoleName: 'Blah', RoleID: id }));
});

console.log(tasks);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;

答案 1 :(得分:0)

这样做怎么样? (我总是讨厌使用for循环,添加我们不需要的其他变量,即索引)

tasks.forEach(task => {
  var roleIds = task.Roles.map(r=>r.RoleID);
  userSelectedRoles.forEach( r => {
   if(roleIds.indexOf(r) === -1){
     task.Roles.push({RoleID: r, RoleName: 'blah'})
   }
  })
})

答案 2 :(得分:0)

如果您想知道错误的位置...在最后一个循环中,您将向角色添加项目。这意味着1级以上的循环现在将再循环1次。而这个循环将添加一个新角色,这将使它再循环一次,这将增加一个角色 - 我认为你现在得到它了:)

使用相同结构的解决方案:在开始循环之前将长度存储在变量中,并将其用于循环次数。

for (var t = 0; t < tasks.length; t++) {
  //CHANGED CODE START
  let rolesLength = task[t].Roles.length;
  // Loop over the roles
  for (var r = 0; r < rolesLength ; r++) {
    //CHANGED CODE END
    // Loop over our user selected roles
    for (var sr = 0; sr < userSelectedRoles.length; sr++) {

      // If this user selected role exists within our roles, continue
      if (tasks[t].Roles[r].RoleID == userSelectedRoles[sr]) {
        // This role exists, no need to do anything
      } else {
        // This user selected role does not exist in our tasks, we need to add it
        tasks[t].Roles.push({
          RoleName: 'Blah',
          RoleID: userSelectedRoles[sr]
        })
      }
    }

  }
}