Javascript 将深度嵌套的属性提取到唯一值数组中

Javascript 将深度嵌套的属性提取到唯一值数组中,javascript,angular,rxjs,Javascript,Angular,Rxjs,考虑到下面的JSON是我的对象,我如何提取userId和roles,将它们分别存储在单独的数组中,而不具有任何重复的值 let rosterInfo = [ { "shiftName": "A", "userDetail": [ { "userId": 'Mary', "roles": ['Operator', 'Supervisor']

考虑到下面的JSON是我的对象,我如何提取userId和roles,将它们分别存储在单独的数组中,而不具有任何重复的值

let rosterInfo = 
    [
        {
           "shiftName": "A",
            "userDetail": [
            {
              "userId": 'Mary',
              "roles": ['Operator', 'Supervisor']
            },
            {
              "userId": 'John',
              "roles": ['Supervisor', Maintenance Technician]
            }
          ]
        },
        {
           "shiftName": "B",
          "userDetail": [
            {
              "userId": 'Crusier',
              "roles": ['Operator', 'Supervisor']
            },
            {
              "userId": 'Philips',
              "roles": ['Operator', 'Supervisor']
            }
          ]
        },
        {
           "shiftName": "C",
             "userDetail": [
            {
              "userId": 'Heath',
              "roles": ['Operator', 'Supervisor']
            },
            {
              "userId": 'Daniel',
              "roles": ['Operator', 'Supervisor']
            }
          ]
        }
    ];
角色的最终数组应为:[“操作员”、“主管”、“维护技术员”] 用户ID的最后一个数组应该是:['Heath','Daniel','Philips','John','Mary','Crusier']

注意:我使用了ForEach和For循环,但这不是理想的解决方案。下面是我使用循环的解决方案

  rosterInfo.forEach(rosterItem => {
  for (let userItem of rosterItem['userDetail']) {
    userItem['roles'].forEach(role => {
      this.rolesInAShift.indexOf(role) > -1
        ? ''
        : this.rolesInAShift.push(role);
    });
  }
});
除此之外,如果我想从上面给定的对象中,如果我想用名字“John”和角色“Supervisor”来过滤上面的对象,那么最终的结果就是这样的

rosterInfo = 
    [
        {
           "shiftName": "A",
            "userDetail": [
            {
              "userId": 'John',
              "roles": ['Supervisor', 'Maintenance Technician']
            }

          ]
        },
        {
           "shiftName": "B",
          "userDetail": [

          ]
        },
        {
           "shiftName": "C",
             "userDetail": [

          ]
        }
    ]
我可以使用循环来实现这一点,但是使用下面的逻辑并不能得到我想要的

 someVar = rosterInfo.map(element => {
        return {
          ...element,
          userDetail: element.userDetail.filter(
            subElement =>
              subElement.roles.indexOf('Supervisor') > -1 &&
              subElement.userId.indexOf('Rajasekhar')
          )
        };
      });

使用
reduce
Set
可以轻松完成。减少到循环,设置为唯一。请检查一下样品

让名册信息=[
{
shiftName:“A”,
用户详细信息:[
{userId:“Mary”,角色:[“Operator”,“Supervisor”]},
{userId:“John”,角色:[“主管”,“维护技术员”]}
]
},
{
shiftName:“B”,
用户详细信息:[
{userId:“Crusier”,角色:[“Operator”,“Supervisor”]},
{userId:“飞利浦”,角色:[“操作员”,“主管”]}
]
},
{
shiftName:“C”,
用户详细信息:[
{userId:“Heath”,角色:[“Operator”,“Supervisor”]},
{userId:“Daniel”,角色:[“操作员”,“主管”]}
]
}
];
const[roles,names]=rosterInfo.reduce(
([角色、名称],i)=>{
i、 userDetail.forEach(x=>{
角色=角色。concat(x.roles);
name.push(x.userId);
});
返回[角色、名称];
},
[[], []]
);
log(Array.from(新集合(角色)),Array.from(新集合(名称))您可以与一起使用删除重复项:

const rosterInfo=
[{“shiftName”:“A”,“userDetail”:[{“userId”:“玛丽”,“角色”:['Operator','Supervisor']},{“userId”:“约翰”,“角色”:['Supervisor','Maintenance Technician']}},{“shiftName”:“B”,“userDetail”:[{“userId”:“Crusier”,“角色”:['Operator','Supervisor']},{“userId”:“飞利浦”,“角色”:['Operator','Supervisor']}},{“shiftName”:“C”,“userDetail”:“userId”:{“userId”,“角色”:['Operator','Supervisor']},{“userId”:'Daniel',“角色”:['Operator','Supervisor']}],
userIds=[…新集合(
罗斯特林福
.map({userDetail})=>
map(({userId}=>userId))
.flat()
)],
角色=[…新集合(
罗斯特林福
.map({userDetail})=>
map(({roles}=>roles))
.单位(2)
)]
console.log(用户ID)
console.log(角色)

.as-console-wrapper{min-height:100%;}
@YevgenGorbunkov角色数组应为:[“操作员”、“主管”、“维护技术员”]用户ID数组应为:[“希思”、“丹尼尔”、“飞利浦”、“约翰”、“玛丽”、“克鲁塞尔”]您好@Yevgen Gorbunkov,您的解决方案对我很有效,我已经更新了问题,请您看一下。@SatyaRam:通过源代码数组查找匹配项(根据两个标准-名称和角色)是完全不同的主题。我建议不要将两者混用。将其作为一个单独的问题发布,我也会很高兴地进行研究。