[英]Find longest occurrence of same number in array
使用 JavaScript,我试图找到一种方法来查找数组中相同数字(在本例中为 1)的最长出现次数。
例如,这是一个示例数组: [2,5,3,1,1,1,3,7,9,6,4,1,1,1,1,1,4,7,2,3,1,1,4,3]
我想编写一个返回“5”的函数,因为数字 1 连续出现 5 次。 (它也连续出现 3 次和 2 次,但我是在最长的一次出现之后)。
到目前为止,我已经写了:
function streak(arr) {
var i,
temp,
streak,
length = arr.length;
for(i=0; i<length; i++) {
if (arr[i] === 1) {
streak += 1;
} else {
temp = streak;
break;
}
}
}
我知道我需要一些方法来知道如果我发现了一个事件我从哪里停止,但我感觉有点卡住了。
任何指针?
我稍微修改了你的函数。 您需要将最高连续记录存储为与当前连续记录不同的变量,并在循环中必要时覆盖该变量 - 最后在函数结束时返回该变量。
function streak(arr) {
var i,
temp,
streak,
length = arr.length,
highestStreak = 0;
for(i = 0; i < length; i++) {
// check the value of the current entry against the last
if(temp != '' && temp == arr[i]) {
// it's a match
streak++;
} else {
// it's not a match, start streak from 1
streak = 1;
}
// set current letter for next time
temp = arr[i];
// set the master streak var
if(streak > highestStreak) {
highestStreak = streak;
}
}
return highestStreak;
}
var array = [2,5,3,1,1,1,3,7,9,6,4,1,1,1,1,1,4,7,2,3,1,1,4,3];
console.log(streak(array)); // 5
如果您还想跟踪最高连续记录的值是多少,请在函数的开头定义另一个变量,在保存最高连续记录时保存它的值,并将其作为数组返回:
// set the master streak var
if(streak > highestStreak) {
highestStreakValue = temp;
highestStreak = streak;
}
}
return [highestStreak, highestStreakValue];
var array = [2,5,3,1,1,1,3,7,9,6,4,'a','a','a','a','a',4,7,2,3,1,1,4,3];
console.log(streak(array)); // [5, "a"]
另一种方法。 我正在将数组转换为字符串。 正则表达式具有反向引用,可确保仅匹配相同字符的序列。 此外,当exec
与g
标志一起使用时,重复执行将从最后一个匹配的末尾开始,而不是从头开始。
var arr = [2,5,3,1,1,1,3,7,9,6,4,1,1,1,1,1,4,7,2,3,1,1,4,3];
var str = arr.join('');
var regex = /(.)\1*/g;
var match;
var largest = '';
while (match = regex.exec(str)) {
largest = match[0].length > largest.length ? match[0] : largest;
}
console.log(largest.length);
您的问题:
streak
大于旧连胜用这个:
function streak(arr) {
var i,
temp,
streak = 1,
maxStreak = 0,
prevNumber,
length = arr.length;
for(i=1; i<length; i++) {
prevNumber = arr[i-1];
if (arr[i] == prevNumber) {
streak += 1;
} else {
if(streak > maxStreak) {
maxStreak = streak;
streak = 1;
}
}
}
return maxStreak;
}
您将需要另外两个数组。
我没有制作代码让你先自己尝试,因为你只是要求一些指针
替代方法:使用正则表达式并将数组转换为字符串。
var arr = [2,5,3,1,1,1,3,7,9,6,4,1,1,1,1,1,4,7,2,3,1,1,4,3];
var str = arr.join('').match(/1+/g);
console.log(process ? process.sort().pop() : "No ocurrences");
您可以使用Array#reduce
并返回实际相同项目序列的起始索引。 如果项目不相等,则检查并更新计数器。
var array = [2, 5, 3, 1, 1, 1, 3, 7, 9, 6, 4, 1, 1, 1, 1, 1, 4, 7, 2, 3, 1, 1, 4, 3], maxCount = 0, maxValues; array.reduce(function (j, a, i, aa) { if (aa[j] === a) { return j; } if (i - j === maxCount){ maxValues.push(aa[j]); } if (i - j > maxCount) { maxCount = i - j; maxValues = [aa[j]]; } return i; }, -1); console.log(maxCount); console.log(maxValues);
这是一种方法:
var values = function(obj) {
var res = [];
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
res.push(obj[i]);
}
}
return res;
};
var countStreak = function(xs) {
var res = xs.reduce(function(acc, x, i) {
if (x === xs[i+1]) {
acc[x] = acc[x]+1 || 2;
} else {
acc[x] = acc[x]-1 || 0;
}
return acc;
},{})
return Math.max.apply(0, values(res));
};
var ns = [2,5,3,1,1,1,3,7,9,6,4,1,1,1,1,1,4,7,2,3,1,1,4,3]
countStreak(ns) //=> 5
我的建议:
function getLongestRow(inputArray) {
// Initialize dummy variables
var start = inputArray[0], curRowLen = 0, maxRowLen = 0, maxRowEle = 0;
// Run through the array
for(var i = 0;i < inputArray.length;i++) {
// If current Element does not belong to current row
if(inputArray[i] != start) {
// If current row is longer than previous rows, save as new longest row
if(curRowLen > maxRowLen) {
maxRowLen = curRowLen;
maxRowEle = start;
curRowLen = 1;
}
// Start new row
start = inputArray[i];
} else {
// Current element does belongt to current row, increase length
curRowLen++;
}
}
// Check whether last row was longer than previous rows
if(curRowLen > maxRowLen) {
maxRowLen = curRowLen;
maxRowEle = start;
}
// Return longest row & element longest row consits of
console.log('The longest row in your array consists of '+maxRowLen+' elements of '+maxRowEle+'.');
}
JsFiddle: http : //jsfiddle.net/hdwp5/
您可以通过查看给定索引中的所有匹配项并跳转到下一个不匹配项的索引来使用更少的迭代。
当剩余的项目少于您找到的最大值时,您也可以退出。
function maxRepeats(arr){
var L= arr.length, i= 0,
max= 1, count= 0;
while(L-i > max){
while(arr[i+count]=== arr[i])++count;
if(count > max) max= count;
i+= count;
count= 0;
}
return max;
}
var A= [2, 5, 3, 1, 1, 1, 3, 7, 9, 6, 4, 1,
1, 1, 1, 1, 4, 7, 2, 3, 1, 1, 4, 3];
最大重复次数(A); 返回 5
找到重复最大次数的多个项目并不容易,因为您必须先找到最大数量才能列出它们。 如果您真的只需要最大数量,请忽略:
function mostRepeats(arr, maximum){
var i= 0, max= maximum || 1,
L= arr.length-max,
count= 0, index= [];
while(i<L){
while(arr[i+count]=== arr[i])++count;
if(count=== maximum) index.push(arr[i]+' starting at #'+i);
else if(count > max) max= count;
i+= count;
count= 0;
}
if(max===1) return 'No repeats';
return maximum? max+' repeats of: '+index.join(', '): mostRepeats(arr, max);
}
var A= [2, 5, 3, 1, 1, 1, 3, 7, 9, 6, 4, 1, 1, 1,
1, 1, 4, 7, 2, 3, 3, 3, 3, 3, 1, 1, 4, 3];
mostRepeats(A);返回:
5 次重复:1 从 #11 开始,3 从 #19 开始
不幸的是,由于缺乏声誉,我还不能发表评论,所以我会将此作为答案发布。 对于我的任务Robbie Averill的解决方案是完美的,但它包含一个小错误。 我有一个由 2 个值组成的数组 - 0 和 1.5,但上面提到的代码只计算“1.5”值,尽管我有“0”在更高的连续重复。 问题是 value 没有在这里进行严格的比较:
if(temp != '' && temp == arr[i]) {
解决方法很简单: if(temp !== '' && temp == arr[i]) {
我已经用这个修复更新了 Robbie 的 jsfiddler: http : //jsfiddle.net/d5X2k/5/
不幸的是,一个问题被标记为重复,但它与这个不同。 所以我必须把我的答案放在这里,对不起……
let tab = [0,0,0,1,1,1,0,0,0,0,1,0,1,1,1,1,1] , arr = [] , n = 0 , res = null ; for(let i of tab) { if ( i ) { ++ n } else if ( n ) { arr.push(n) ; n = 0 } } arr.push(n) ; res = Math.max(...arr); console.log("Streak with 1 is ", Math.max(...arr));
正如您所看到的,这是一个比 reduce 更慢的更好的解决方案:
let tab = [0,0,0,1,1,1,0,0,0,0,1,0,1,1,1,1,1]; let arr = []; let n = 0; let res = null; let loop = 0; let start = new Date().getTime(); while (loop < 1000000){ ++ loop; arr = []; for(let i of tab) { if ( i ) { ++ n } else if ( n ) { arr.push(n) ; n = 0 } } arr.push(n); res = Math.max(...arr); } let end = new Date().getTime(); console.log("laps old fashion = ", end - start); loop = 0; let streaks = null; start = new Date().getTime(); while (loop < 1000000){ ++ loop; streaks = tab.reduce((res, n) => (n ? res[res.length-1]++ : res.push(0), res) , [0]); res = Math.max(...streaks); } end = new Date().getTime(); console.log("laps reduce = ", end - start); console.log("Streak with 1 is ", Math.max(...arr));
输入数组:
const seq = [
0, 0, 0,
1, 1, 1,
1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
];
最短的解决方案:
console.log(Math.max(...Array.from(seq.join("").matchAll(/(.)\1+/g), m=>m[0].length)))
使用正则表达式替代(剧透:它比使用 reduce() 的解决方案慢约 25%。请参阅下面的“使用 reduce() 的现代方法” ):
const longestSeq = (seq) => {
let max = 0;
seq.join("").replace(/(.)\1+/g, m=> max = Math.max(max, m.length));
return max;
};
直截了当,老派风格,人类可读和最快的解决方案:
let longestSeq = () => {
let maxCount = 0,
curCount = 0,
curItem, prevItem,
l = seq.length+2, // +1+1 to finish last sequence and compare 'undefined' with previous
i = 0;
for (; i < l; ++i) {
curItem = seq[i];
if (curItem === prevItem) ++curCount;
else {
if (curCount > maxCount) maxCount = curCount;
curCount = 1;
prevItem = curItem;
}
}
return maxCount;
}
使用 reduce() 的现代方法(只是比上面的老式代码慢一点):
const longestSeq = (seq) => seq
.reduce(
({count, max}, item) => item === 0
? { count: ++count, max: Math.max(count, max) }
: { count: 0, max: max },
{ count: 0, max: 0} )
.max;
性能测试,Reduce() 与老式 for(): https : //jsbench.me/ifkgsin56z/1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.