lodash按属性数组数组过滤

时间:2015-12-24 01:09:08

标签: javascript arrays filtering lodash

我有一系列拥有属性数组'权利'我想过滤掉拥有特定权利的用户。我希望按数组进行过滤,以便我希望所有拥有完整权限的用户['完整']或具有完整权限和编辑功能的用户['完整','编辑& #39]。我对使用lodash相当新,我认为我可以将它们连在一起,但我不确定这是否有更有效的方法。

这是我的傻瓜:http://plnkr.co/edit/5PCvaDJaXF4uxRowVBlK?p=preview

结果['完整']:

[{
    "name": "Company1 Admin",
    "rights": [
      "full"
    ]
  },
  {
    "name": "FullRights Company1",
    "rights": [
      "full","review"
    ]
  }]

结果['完整','编辑']:

[{
    "name": "Company1 Admin",
    "rights": [
      "full"
    ]
  },
  {
    "name": "FullRights Company1",
    "rights": [
      "full","review"
    ]
  },
  {
    "name": "EditRights Company1",
    "rights": [
      "edit"
    ]
  }]

代码:



var users = [
      {
        "name": "Company1 Admin",
        "rights": [
          "full"
        ]
      },
      {
        "name": "FullRights Company1",
        "rights": [
          "full","review"
        ]
      },
      {
        "name": "ApproveRights Company1",
        "rights": [
          "approve","review"
        ]
      },
      {
        "name": "EditRights Company1",
        "rights": [
          "edit"
        ]
      },
      {
        "name": "ReviewRights Company1",
        "rights": [
          "review"
        ]
      },
      {
        "name": "NoRights Company1",
        "rights": [
          "none"
        ]
      }
    ];
        
var tUsers = [];
var filterRights = ['full','edit'];
_.forEach(users, function(user) {
    if (_.intersection(user.rights, filterRights).length > 0) {
      tUsers.push(user);
    }
}) ;        
        
//console.log('users', JSON.stringify(users, null, 2)); 
console.log('tUsers', JSON.stringify(tUsers, null, 2));  
        

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
&#13;
&#13;
&#13;

3 个答案:

答案 0 :(得分:3)

来自docs

  

_。filter(collection,predicate,thisArg);

     

参数

     
      
  • collection(Array | Object | string):要迭代的集合。

  •   
  • [predicate = _。identity](函数|对象|字符串):每次迭代调用的函数。

  •   
  • [thisArg](*):谓词的这种绑定。

  •   

当您想要连接不同的处理步骤时,链接很棒。

如果你的问题陈述是

  1. 按权利过滤
  2. 按年龄最大的人排序
  3. 采取10
  4. 然后链接会很有意义。

    此问题似乎主要是过滤时的自定义逻辑。

    var users = [/* Your user data here */];
    function filterByRights (users, rights) {
        return _.filter(users, function (user) {
            return _.any(user.rights, function (right) {
                return _.contains(rights, right);
            });
        });
    }
    filterByRights(users, ['full', 'edit']); // [/*Users with full or edit rights*/]
    

    我认为我的例子很好,因为它不依赖条件逻辑。它使用lodash定义的方法,如anycontains

    性能问题

    我想扩展您对性能的担忧。以下是几点。

    • 您的问题代码正在维护自己的过滤用户的机制。虽然这是一个非常好的解决方案,但你应该选择让那些维护lodash的人处理这个逻辑。他们可能花了很多时间来优化如何从原始阵列创建另一个阵列。

    • _.any_.intersection效率更高。 _.intersection需要处理每个元素以了解交集是什么。 _.any在遇到传递谓词的第一个元素时停止,否则它会检查每个元素。这一点很小,因为有少量的&#34;权利&#34;

    • 我给出的例子可能更多&#34; lodash标准&#34;。您通常可以使用lodash定义的方法和普通谓词完全进行数据转换。

答案 1 :(得分:2)

以下是@ t3dodson答案的更新。如果使用当前(4.17.4)Lodash版本:

,现在应该使用以下代码段
function filterByRights (users, rights) {
  return _.filter(users, function (user) {
    return _.some(user.rights, function (right) {
      return _.includes(rights, right);
    });
  });
}

来自Changelog

  

删除了_.contains,转而使用_.includes

     

删除_.any支持_.some

答案 2 :(得分:1)

我认为你使用intersection()走在正确的道路上(我从未见过这个功能有任何性能问题)。以下是我使用flow()组成一个iteratee的方法:

_.filter(users, _.flow(
    _.property('rights'), 
    _.partial(_.intersection, filterRights), 
    _.size
));

property()函数获取rights属性,并将其传递给intersection()。我们已经部分应用了filterRights数组。最后,size()函数是将 thruthy / falesy 值传递给filter()所必需的。