JS:Lodash通过谓词数组进行分区

时间:2018-08-19 10:52:31

标签: javascript ecmascript-6 lodash

我有以下工作要为我工作。只是好奇是否有一种“更好”的方法。

var users = [
  { 'user': 'barney',  'age': 36, 'active': false },
  { 'user': 'fred',    'age': 40, 'active': true },
  { 'user': 'pebbles', 'age': 1,  'active': false }
];
 
_.partition(users, ({user}) => {
   if (_.includes(['fred', 'pebbles'], user)) {
      return true
   } else {
     return false
   }
})

不知道此解决方案对大量用户的可扩展性如何?

2 个答案:

答案 0 :(得分:2)

对我来说这是一个有趣的问题。我准备了一些度量代码。也许这可以帮助您做出正确的决定。

关于您的问题,我相信,如果您需要最高的性能,则必须使用最少的复杂代码。 Lodash是一个很棒的工具,它使代码更具可读性,但是当您需要性能时,这并不是选择。

(function() {
    const users = [
      { 'user': 'barney',  'age': 36, 'active': false },
      { 'user': 'fred',    'age': 40, 'active': true },
      { 'user': 'pebbles', 'age': 1,  'active': false }
    ];

    function function1 (queryArray) {
      return _.partition(users, ({user}) => _.includes(queryArray, user));
    }
    function function2 (queryArray) {
        const _output = [[], []];
        users.reduce((output, user) => {
            if(queryArray.indexOf(user.user) > -1) output[0].push(user);
            else output[1].push(user);
            return output;
        }, _output);
        return _output;
    }
    function function3 (queryArray) {
        const output = [[], []];
        for(let i = 0; i < users.length; i++){
            const user = users[i];
            if(queryArray.indexOf(user.user) > -1) output[0].push(user);
            else output[1].push(user);
        }
        return output;
    }


    const iterations = 1000000;
    const queryArray = ['fred', 'pebbles'];

    console.time('Function #1');
    for(let i = 0; i < iterations; i++ ){
        function1(queryArray);
    }
    console.timeEnd('Function #1');

    console.time('Function #2');
    for(let i = 0; i < iterations; i++ ){
        function2(queryArray);
    }
    console.timeEnd('Function #2');

    console.time('Function #3');
    for(let i = 0; i < iterations; i++ ){
        function3(queryArray);
    }
    console.timeEnd('Function #3');
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

这是我机器上的结果。您的浏览器中可能还有其他结果,但是该比率将大致相同。平均来说,lodash解决方案所花费的时间大约是其两倍。

Function #1: 787.700ms
Function #2: 466.300ms
Function #3: 275.900ms

答案 1 :(得分:1)

首先,请注意if (someBoolean) { return true; } else { return false; }完全等同于return someBoolean。因此,您的代码可以简化:

const [fredOrPebblesUsers, otherUsers] = 
  _.partition(users, ({user}) => _.includes(['fred', 'pebbles'], user));

现在,它的可扩展性如何?好了,您已经在内存中拥有users的完整数组,您只需要再创建两个带有对这些对象的引用(而不是值本身)的数组。如果需要一次使用所有分区值,则应该知道如何使用这些分区值,否则像lazy.js这样的惰性库会有所帮助。

速度方面,@ Max Martynov已经讨论了箭头功能上for循环的增益。 IMO,只有当您看到这是应用程序的瓶颈时,才应使用箭头功能更改漂亮的抽象,以实现笨拙的for循环。

  

_。includes(['fred','pebbles'],用户)

要比较两个值吗?如果您的实际代码具有更多值,则应使用Set进行O(1)比较,而不是O(n)。