我有一个条件,可以通过Array.prototype.some()
进行检查。考虑这个数组:
const coolArray = [
{ isCool: false },
{ isCool: false },
{ isCool: true }
]
const isCool = coolArray.some(item => item.isCool === true)
if (isCool) {
console.log("hello I'm cool!")
}
但是,我希望在item.isCool
为true
并且数组中至少有两项符合条件时进行检查。因此,上面的示例将不会输出该消息,因为只有一个true
条件。
在MDN上,此方法的引用为arr.some(callback(element[, index[, array]])[, thisArg])
。但是[, array]
引用原始数组而不是其克隆,因此执行以下操作将输出相同的结果:
const isCool = coolArray.some((item, index, arr) => {
return item.isCool === true && arr.length > 1
})
我知道我可以避免.some()
并使用map
或for
遍历数组并将结果保存在外部数组中,这样我就可以检查长度了,类似于:
const isCoolArr = []
coolArray.map(item => item.isCool ? isCoolArr.push(item) : false)
console.log('expected result:', isCoolArr.length) // outputs 1
但是我对使用这种方法并寻找更简单的替代方法并不特别满意。 .some()
是否可以满足我的需要,或者我需要其他替代方法?除了我上面提到的情况以外,还有其他吗?
答案 0 :(得分:2)
使用.filter()
,您将失去使用.some()
所获得的短路优势。一种选择是使用回调外部的变量。
const coolArray = [{isCool: false},{isCool: false},{isCool: true}]
let count = 0
const isCool = coolArray.some(item => (count += item.isCool) >= 2)
if (isCool) {
console.log("hello I'm cool!")
} else {
console.log("not cool enough")
}
这利用了将布尔值转换为数字的优势。如果您不喜欢,可以更加明确。
const coolArray = [{isCool: false},{isCool: false},{isCool: true}]
let count = 0
const isCool = coolArray.some(item => item.isCool && ++count >= 2)
if (isCool) {
console.log("hello I'm cool!")
} else {
console.log("not cool enough")
}
或者在不添加额外变量的情况下实现!
const coolArray = [{isCool: false},{isCool: false},{isCool: true}]
let isCool = 0;
isCool = coolArray.some(item => item.isCool && ++isCool >= 2);
if (isCool) {
console.log("hello I'm cool!")
} else {
console.log("not cool enough")
}
答案 1 :(得分:2)
Array.reduce
const coolArray = [
{ isCool: false },
{ isCool: false },
{ isCool: true }
]
const count = coolArray.reduce((accum, item) => Number(item.isCool) + accum, 0)
if (count >= 2) {
console.log("Hello I'm cool!")
}
答案 2 :(得分:1)
您可以使用filter并检查长度
const coolArray = [
{ isCool: false },
{ isCool: false },
{ isCool: true }
]
const isCool = coolArray.filter(item => item.isCool === true)
if (isCool.length > 1 ) {
console.log("hello I'm cool!")
} else{
console.log('length is less than 2')
}
答案 3 :(得分:1)
其他人建议使用filter
并检查length
。我想在atLeast创建一个方法,如果满足条件,该方法将会中断
const coolArray = [
{ isCool: false },
{ isCool: false },
{ isCool: true }
]
function x(cb,num){
let count = 0;
for(let i =0;i<this.length;i++){
if(cb(this[i],i,this)) count++;
if(count === num) return true;
}
return false;
}
Object.defineProperty(Array.prototype,'atLeast',{
value:x,
writeable:true
})
console.log(coolArray.atLeast(x => x.isCool === true,1)); //true
console.log(coolArray.atLeast(x => x.isCool === true,2)); //false
答案 4 :(得分:1)
这是一个简单的通用实现,一旦达到限制就会停止:
let someTimes = (array, fn, count) => array.some(x => !(count -= Boolean(fn(x))));
console.log(someTimes(
[1,2,3,44,5,66,7,99],
x => x > 10,
2
))
或者甚至更好,
let countDown = (fn, count) => x => !(count -= !!fn(x));
console.log(
[1, 2, 3, 44, 5, 66, 7, 99].some(countDown(x => x > 10, 2))
)
在大多数情况下,提早退出优化并不值得,您可以简单地使用更有用的通用计数器函数:
let countWhere = (array, fn) => array.reduce((n, x) => n + Boolean(fn(x)), 0);
console.log(countWhere(
[1,2,3,44,5,66,7,99],
x => x > 10
) >= 2)