如何在javascript(es6)中展平对象属性数组has array has array?

如何在javascript(es6)中展平对象属性数组has array has array?,javascript,ecmascript-6,mapreduce,Javascript,Ecmascript 6,Mapreduce,给定一个树形对象: 用户有许多角色 角色有许多权限集合 PermissionCollection具有许多权限 如何使用javascript将其扁平化,最终得到一个权限数组 比如: user.roles.map(r = r.permissionGroups).flatten().reduce(pg => pg.permissions).flatten(); 这是一个典型的地图缩小问题吗?这里有一个(浅层)展平函数: var flatten = array => array.red

给定一个树形对象:

  • 用户有许多角色
  • 角色有许多权限集合
  • PermissionCollection具有许多权限
如何使用javascript将其扁平化,最终得到一个权限数组

比如:

user.roles.map(r = r.permissionGroups).flatten().reduce(pg => pg.permissions).flatten();
这是一个典型的地图缩小问题吗?

这里有一个(浅层)展平函数:

var flatten = array => array.reduce( ( a, b ) => a.concat( b ), [] );
你可以这样应用它

var permissionGroups = flatten( user.roles.map( r => r.permissionGroups ) );
var permissions = flatten( permissionGroups.map( pg => pg.permissions ) );
下面是一个(浅)展平函数:

var flatten = array => array.reduce( ( a, b ) => a.concat( b ), [] );
你可以这样应用它

var permissionGroups = flatten( user.roles.map( r => r.permissionGroups ) );
var permissions = flatten( permissionGroups.map( pg => pg.permissions ) );

您是正确的,
reduce()
可能会提供最干净的方法

您可以
concat()
将阵列组合在一起:

const allPermissions = user.roles.reduce((r, role) => 
  r.concat(role.permissionGroups.reduce((r, group) => 
    r.concat(group.permission), []), 
  []);
请注意,它每次返回时实际上都会创建一个新数组,因此如果有很多角色,它可能会有点效率低下。要在每次不创建新数组的情况下执行此操作,可以使用
push.apply()

const allPermissions = user.roles.reduce((r, role) => 
  r.push.apply(r, role.permissisionGroups.reduce((r, group) => 
    r.push.apply(r, group.permissions), []), 
  []);
使用
apply()
可以将权限作为参数传入(基本上与多次调用
push()
相同)。若您尝试推送数组,它会将其作为数组而不是单个值推送

如果要更进一步,并始终保持一个阵列,可以使用:

const allPermissions=[]; user.roles.forEach(角色=> role.permissionGroups.forEach(组=> allPermissions.push.apply(allPermissions,group.permissions) ) )

这基本上仍然是一种
reduce()
模式,但不会创建很多额外的值。如果您想使用
reduce()
,它可以如下所示:

const allPermissions = user.roles.reduce((r, role) =>
  r.push.apply(r, role.permissionGroups.reduce((r, group) =>
    r.push.apply(r, group.permissions)), r), 
  []
);

您是正确的,
reduce()
可能会提供最干净的方法

您可以
concat()
将阵列组合在一起:

const allPermissions = user.roles.reduce((r, role) => 
  r.concat(role.permissionGroups.reduce((r, group) => 
    r.concat(group.permission), []), 
  []);
请注意,它每次返回时实际上都会创建一个新数组,因此如果有很多角色,它可能会有点效率低下。要在每次不创建新数组的情况下执行此操作,可以使用
push.apply()

const allPermissions = user.roles.reduce((r, role) => 
  r.push.apply(r, role.permissisionGroups.reduce((r, group) => 
    r.push.apply(r, group.permissions), []), 
  []);
使用
apply()
可以将权限作为参数传入(基本上与多次调用
push()
相同)。若您尝试推送数组,它会将其作为数组而不是单个值推送

如果要更进一步,并始终保持一个阵列,可以使用:

const allPermissions=[]; user.roles.forEach(角色=> role.permissionGroups.forEach(组=> allPermissions.push.apply(allPermissions,group.permissions) ) )

这基本上仍然是一种
reduce()
模式,但不会创建很多额外的值。如果您想使用
reduce()
,它可以如下所示:

const allPermissions = user.roles.reduce((r, role) =>
  r.push.apply(r, role.permissionGroups.reduce((r, group) =>
    r.push.apply(r, group.permissions)), r), 
  []
);

啊,对了,这很好读。下划线已经变平了,所以猜测做同样的事情…现在将尝试一下。啊,对了,这很好,很容易阅读。下划线已经变平了,所以猜猜也可以…现在可以试试了。答案很好。谢谢你的解释。我想我更喜欢本·韦斯特的答案,完全是基于它的可读性——尽管我听到你说的是:效率低下。然而,我们谈论的是每个阵列中的10个项目…很好的答案。谢谢你的解释。我想我更喜欢本·韦斯特的答案,完全是基于它的可读性——尽管我听到你说的是:效率低下。然而,我们谈论的是每个阵列中的10个项目。。。