Lodash:从多个构造单个对象 - 合并/覆盖属性 [英] Lodash: Constructing single object from many - Merging/overriding properties

查看:547
本文介绍了Lodash:从多个构造单个对象 - 合并/覆盖属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


注意:我在lodash下提交了这个问题,因为我很确定它可以帮助我很好地解决这个问题,但是现在还没有把它放在它上面

Note: I filed this question under lodash as I'm pretty sure it can help me solve that problem nicely, but haven't put my finger on it just now

我有一个描述不同用户角色及其权限的对象;

I have an object describing different user roles and their permissions;

我会有类似10的东西-15角色定义为像这样(这不反映应用程序代码,但问题本身):

I will have something like 10-15 roles defined "like this" (this doesn't reflect the application code but the problem itself):

    var role1 = {
    views: {
        v1: {access: true},
        v2: {access: false},
        v#: {access: false}
    }
}

var role2 = {
    views: {
        v1: {access: false},
        v2: {access: true},
        v3: {access: true},
    }
}

连接的用户将具有多个角色;在该示例中,它可能是 ['role1','role2'] ,并且我需要构建一个权限对象将是所有用户角色中定义的所有道具的组合。

The user connected will have multiple roles; In that example it could be ['role1', 'role2'], and out of this I need to construct a single permissions object that will be a combination of all the props defined in all the user roles.

它基本上是基于白名单的,其中所有true属性都应该覆盖任何被定义为假的东西。因此,预期结果应为:

It is basically whitelist-based, where all "true" properties should override anything that was defined as false. Thus, the expected result should be:

permissions = {
    views: {
        v1: {access: true},
        v2: {access: true},
        v2: {access: true}
    }
}






我不太确定如何在不依赖疯狂的嵌套循环的情况下解决这个问题


I'm not too sure how to tackle that one without relying on crazy nested loops

以下是JSBin的起点: http://jsbin.com/usaQejOJ/ 1 /编辑?js,控制台

Here's a starting point in JSBin: http://jsbin.com/usaQejOJ/1/edit?js,console

感谢您的帮助!

推荐答案

Lodash有一些方法可以帮助优雅地解决这个问题。

Lodash has a few methods that will help to elegantly solve this problem.

首先, 合并 方法。它需要多个源对象,并以递归方式将它们的属性合并到一个目标对象中。如果两个对象具有相同的属性名称,则后一个值将覆盖前者。

First of all, the merge method. It takes multiple source objects, and recursively merges their properties together into a destination object. If two objects have the same property name, the latter value will override the former.

这几乎是我们想要的;它会将您的角色对象合并为一个对象。我们不想要的是覆盖行为;我们希望 true 值始终覆盖 false 。幸运的是,您可以传递自定义合并函数,并且当两个对象具有相同的键时,lodash的 merge 将使用它来计算合并值。

This is almost what we want; it'll merge your role objects together into a single object. What we don't want is that override behavior; we want true values to always override false ones. Luckily, you can pass in a custom merge function, and lodash's merge will use that to compute the merged value when two objects have the same key.

我们会将自定义函数写入逻辑您的项目(而不是以后允许 false 要覆盖的值 true s。),这样如果任一值为 true ,则生成的合并值将为是 true

We'll write a custom function to logically OR your items together (instead of allowing later false values to override trues.), so that if either value is true, the resulting merged value will be true.

因为我们的对象是嵌套的,所以我们需要确保我们的自定义合并功能只做当它比较布尔值时,这个 OR 。在比较对象时,我们希望对其属性进行正常合并(再次使用我们的自定义函数进行合并)。它看起来像这样:

Because our objects are nested, we'll need to make sure our custom merge function only does this OR when it's comparing boolean values. When comparing objects, we want to do a normal merge of their properties (again using our custom function to do the merge). It looks something like this:

function do_merge(roles) {

  // Custom merge function ORs together non-object values, recursively
  // calls itself on Objects.
  var merger = function (a, b) {
    if (_.isObject(a)) {
      return _.merge({}, a, b, merger);
    } else {
      return a || b;
    }
  };

  // Allow roles to be passed to _.merge as an array of arbitrary length
  var args = _.flatten([{}, roles, merger]);
  return _.merge.apply(_, args);
}

do_merge([role1, role2, role3]);

Lodash以另一种方式提供帮助:您可能会从文档中注意到 _.merge 不接受要合并的对象数组;你必须作为参数传递它们。但在我们的例子中,数组非常方便。

Lodash helps out in one other way: You may notice from the docs that _.merge doesn't accept an array of objects to merge together; you have to pass them in as arguments. In our case, though, an array would be awfully convenient.

为了解决这个问题,我们将使用JavaScript的 apply 方法,允许您通过以下方法调用方法将其参数作为数组传递,并使用Lodash方便的 flatten 方法,该方法采用可能包含嵌套数组的数组 - 如 [1,[2,3] ],[4,5]] - 并将其展平为 [1,2,3,4,5]

To get around this, we'll use JavaScript's apply method, which allows you to invoke a method by passing its arguments as an array, and Lodash's handy flatten method, which takes an array that might contain nested arrays — like [1, [2, 3], [4, 5]] — and flattens it into [1, 2, 3, 4, 5].

所以我们将在 flatten ed数组中收集我们需要的所有参数,然后 apply 他们到合并

So we'll gather up all the arguments we need in a flattened array, and then apply them to merge!

如果您的对象嵌套得非常深,那么就有机会你将像这样以递归方式调用 merger 堆栈,但是对于你的对象,这应该可以正常工作。

If your objects are nested very very deeply, there's a chance you'll overflow the stack calling merger recursively like this, but for your objects this should work just fine.

这篇关于Lodash:从多个构造单个对象 - 合并/覆盖属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆