如何使用Underscore来select最大的数组元素

How to use Underscore to select the largest array element

我有以下数组:

var array = [[{key1: 1, key2: thing}, {key1: 3, key2: thing}],
 [{key1: 4, key2: stuff}, {key1: 2, key2: stuff}],
 [{key1: 3, key2: onlyOne}]]

我需要取出所有少于两个对象的数组,每个剩余的数组可能有 'n' 个对象应该只包含具有最小 key1 的对象。最后我会:

var updatedArray = [[{key1: 1, key2: thing}],[{key1: 2, key2: stuff}]]

我怎样才能使用 Underscore 得到这个?

现在我已经完成了:

var soFar = _.filter(_.groupBy(_.map(array, function(n){return _.find(n)}), 
"key2"), function(n){return n.length > 1});

//soFar = [[{key1: 1, key2: thing}, {key1: 3, key2: thing}], 
//[{key1: 4, key2: stuff}, {key1: 2, key2: stuff}]]`

这让我摆脱了只有一个对象的数组,但我无法根据对象的比较找出下一部分来修改每个数组。

看来你把事情复杂化了。这是一个纯 ES5 示例,但很容易转换为 underscore' 语法。

var thing = 'thing';
var stuff = 'stuff';
var onlyOne = 'onlyOne';
var array = [
  [{
    key1: 1,
    key2: thing
  }, {
    key1: 3,
    key2: thing
  }],
  [{
    key1: 4,
    key2: stuff
  }, {
    key1: 2,
    key2: stuff
  }],
  [{
    key1: 3,
    key2: onlyOne
  }]
];
var b = array.filter(function(item) {
  return item.length > 1;
}).map(function(item) {
  return [item.slice().sort(function(x, y) {
    return x.key1 - y.key1;
  }).shift()];
});
document.getElementById('out').textContent = JSON.stringify(b, null, 2);
console.log(b);
<pre id="out"></pre>

下划线

var thing = 'thing';
var stuff = 'stuff';
var onlyOne = 'onlyOne';
var array = [
  [{
    key1: 1,
    key2: thing
  }, {
    key1: 3,
    key2: thing
  }],
  [{
    key1: 4,
    key2: stuff
  }, {
    key1: 2,
    key2: stuff
  }],
  [{
    key1: 3,
    key2: onlyOne
  }]
];
var b = _.chain(array).filter(function(item) {
  return item.length > 1;
}).map(function(item) {
  return [_.chain(item).map(_.identity).sortBy('key1').first()];
});

document.getElementById('out').textContent = JSON.stringify(b, null, 2);
console.log(b);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<pre id="out"></pre>

或者您可以使用 reduce 而不是 filtermap 并为自己保存一个循环以及 chain 包装器。

var thing = 'thing';
var stuff = 'stuff';
var onlyOne = 'onlyOne';
var array = [
  [{
    key1: 1,
    key2: thing
  }, {
    key1: 3,
    key2: thing
  }],
  [{
    key1: 4,
    key2: stuff
  }, {
    key1: 2,
    key2: stuff
  }],
  [{
    key1: 3,
    key2: onlyOne
  }]
];
var b = _.reduce(array, function(acc, item) {
  if (item.length > 1) {
   acc.push([_.chain(item).map(_.identity).sortBy('key1').first()]);
  }
  return acc;
}, []);

document.getElementById('out').textContent = JSON.stringify(b, null, 2);
console.log(b);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<pre id="out"></pre>

而不是 slice(或 map)和 sort(或 sortBy),您可以使用 min 并进一步减少 chain

var thing = 'thing';
var stuff = 'stuff';
var onlyOne = 'onlyOne';
var array = [
  [{
    key1: 1,
    key2: thing
  }, {
    key1: 3,
    key2: thing
  }],
  [{
    key1: 4,
    key2: stuff
  }, {
    key1: 2,
    key2: stuff
  }],
  [{
    key1: 3,
    key2: onlyOne
  }]
];
var b = _.reduce(array, function(acc, item) {
  if (item.length > 1) {
    acc.push([_.min(item, 'key1')]);
  }
  return acc;
}, []);

document.getElementById('out').textContent = JSON.stringify(b, null, 2);
console.log(b);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<pre id="out"></pre>

如果您使用 lodash 而不是 underscore,它会提供进一步的改进。

没有underscore.js,使用普通 ES

Step1 : 过滤数组大于1 children

Step2 : 克隆数组,避免不需要的突变。使用 map 函数 return 按 key1 对 child 数组进行升序排序 return 第一个元素

array.filter((a,n)=>{ return a.length>1;  })
   .map((i)=>{  
          var a = i.slice(0); 
           return a.sort((a,b)=>{ return a.key1 > b.key1 })[0]; 
    });

使用underscore.js

 var resultArray = _.map(_.filter(arr,(a,n)=>{ 
         return a.length>1;  
      }),(i)=>{  
       var a = i.slice(0); 
       return a.sort(function(a,b){ return a.key1 > b.key1 })[0];        
  });

这是根据 OP 要求使用 undersore/lodash 的答案:

var array = [
    [{
        key1: 1,
        key2: 'thing'
    }, {
        key1: 3,
        key2: 'thing'
    }],
    [{
        key1: 4,
        key2: 'stuff'
    }, {
        key1: 2,
        key2: 'stuff'
    }],
    [{
        key1: 3,
        key2: 'onlyOne'
    }]
];

array = _.filter(array, function(v) {
    return v.length >= 2;
});

array = _.map(array, function(v) {
    v.sort(function(a, b) {
        return a.key1 > b.key1;
    });
    return [v[0]];
});


console.log(array);

第二种方法,我们将 map 和 filter 函数合并到一个语句中。接下来有点混乱。

var array = [
    [{
        key1: 1,
        key2: 'thing'
    }, {
        key1: 3,
        key2: 'thing'
    }],
    [{
        key1: 4,
        key2: 'stuff'
    }, {
        key1: 2,
        key2: 'stuff'
    }],
    [{
        key1: 3,
        key2: 'onlyOne'
    }]
];

array = _.map(_.filter(array, function(v) {
    return v.length >= 2;
}), function(v) {
    v.sort(function(a, b) {
        return a.key1 > b.key1;
    });
    return [v[0]];
});


console.log(array);

输出: