var aa = [
{ 'id': 0, 'age': 16 },
{ 'id': 1, 'age': 16 },
{ 'id': 2, 'age': 12 },
{ 'id': 3, 'age': 16 },
{ 'id': 4, 'age': 16 },
{ 'id': 5, 'age': 16 }
]
怎么查找出 连续age=16 的次数
结果是3
var aa = [
{ 'id': 0, 'age': 16 },
{ 'id': 1, 'age': 16 },
{ 'id': 2, 'age': 12 },
{ 'id': 3, 'age': 16 },
{ 'id': 4, 'age': 16 },
{ 'id': 5, 'age': 16 }
]
怎么查找出 连续age=16 的次数
结果是3
如果数据量较少的话,使用循环的方式就可以了。如果数据量较大,则可以利用已经查找到的最大匹配值信息值来做查找上的优化。
const findRepeatForward = (
startIndex,
curForward = 1,
options = {},
forward = curForward
) => {
const { maxIndex } = options;
let lastIndex = startIndex + curForward;
if (lastIndex > maxIndex) {
// 如果最后的值已经超出数组最大范围
// 则表示后续值不需要再判断
return {
forward,
index: maxIndex + 1,
};
} else {
// 从后往前查找索引
const { findHandle } = options;
let prevIndex = lastIndex;
while (prevIndex > startIndex) {
if (findHandle(values[prevIndex])) {
prevIndex--;
} else {
break;
}
}
if (prevIndex === startIndex) {
// 全部匹配,继续往后查找,进一步更新forward值
let index = lastIndex + 1;
for (; index <= maxIndex; index++) {
if (findHandle(values[index])) {
forward++;
} else {
break;
}
}
return {
found: true,
forward: forward + 1,
index: index + 1,
};
} else if (prevIndex === lastIndex) {
// 一个匹配都没有
return {
forward,
index: lastIndex + 1,
};
} else {
// 找到部分匹配,递归找到完全匹配或完全不匹配为止
let equalCount = lastIndex - prevIndex;
return findRepeatForward(
lastIndex,
forward - equalCount + 1,
options,
forward
);
}
}
};
const getContinousCount = (values, findHandle) => {
const maxIndex = values.length - 1;
let i = 0;
let forward;
while (i <= maxIndex) {
const curItem = values[i];
if (findHandle(curItem)) {
const result = findRepeatForward(i, forward, {
maxIndex,
values,
findHandle,
});
i = result.index;
forward = result.forward;
} else {
i++;
}
}
return forward ?? 0;
};
console.log(getContinousCount(aa, it => it.age === 16));
小数据量的情况下性能上没有太大的差别,当数据量较大的时候,最大重复值越大,找到的时间越早,使用以上方式查找性能就越好。相比常规方式大概有3倍以上的性能提升(如果不是数据量特别大或者执行次数特别多,这点性能提升可能也没有多大意义),仅为了探索,用了上面两位大大的方案对比做了个简单的性能测试:jsbin性能测试 感兴趣的同学可以看一看~
遍历就行,遇到不是16的记录然后归零,然后返回记录最大值。
const aa = [{'id':0, 'age': 16},{'id':1, 'age': 16},{'id':2, 'age': 12},{'id':3, 'age': 16},{'id':4, 'age': 16},{'id':5, 'age': 16}]
let res=0
let now=0
for (const i of aa) {
if (i.age==16){
now++
}else{
if (res<now){
res=now
}
now=0
}
}
if (res<now){
res=now
}
console.log(res);
function count(arr, key, value) {
var ret = 0;
for (var i = 0, j = 0; i < arr.length; ++i) {
if (arr[i][key] !== value) j = 0;
else if (ret < ++j) ret = j;
}
return ret;
}
console.dir(count(aa, "age", 16));
10 回答11.2k 阅读
5 回答4.8k 阅读✓ 已解决
4 回答3.1k 阅读✓ 已解决
2 回答2.7k 阅读✓ 已解决
3 回答2.3k 阅读✓ 已解决
3 回答2.2k 阅读✓ 已解决
2 回答2.6k 阅读✓ 已解决
@miganzi 的思路非常好,不过代码略微复杂了一点。这个算法的核心就是:既然我已经找到了最大 count,那下次直接跳过最大 count 数,如果正好命中,那就向前向后双向统计汇总出来看是否最大,否则继续跳过最大连续数……
按这个思路写的代码(看注释)
也做了性能对比,在这里 JSBench.me 上的性能对比。