在数组中查找最长出现的相同数字

时间:2014-05-16 00:07:52

标签: javascript arrays

使用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;
        }
    }
}

我知道如果我发现了一个事件,我需要某种方式知道我离开的地方,但我感觉有些卡住了。

任何指针?

12 个答案:

答案 0 :(得分:6)

我稍微修改了你的功能。你需要将最高条纹存储为当前条纹的一个单独变量,并在循环中覆盖必要的变量 - 最后在函数末尾返回该变量。

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"]

<强> Demo returning both

答案 1 :(得分:2)

另一种方法。我将数组转换为字符串。正则表达式具有backrefence,可确保只匹配相同字符的序列。此外,当execg标志一起使用时,重复执行将从最后一场比赛结束开始,而不是从头开始。

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);

答案 2 :(得分:1)

你的问题:

  • 您不存储当前条纹
  • 您没有指定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;
}

Demo

答案 3 :(得分:1)

这里你需要另外两个阵列。

  1. 使用循环
  2. 存储源数组中的不同数字
  3. 制作第二组数组,该数组等于具有不同数字的第一组数组的长度。
  4. 使循环等于第一组数组的长度,然后根据索引将值推送到第二组数组。
  5. 使用第二组数组再次循环,然后使用第二个数组的索引找到最多的数据
  6. 最后,使用从步骤4获得的索引从第一组数组中获取数字。
  7. 我没有为你自己尝试代码,因为你只是要求一些指针

答案 4 :(得分:1)

替代方法:使用regexp并将数组转换为字符串。

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");

答案 5 :(得分:1)

您可以取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);

答案 6 :(得分:0)

这是一种方法:

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

答案 7 :(得分:0)

我的建议:

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/

答案 8 :(得分:0)

通过展望给定索引的所有匹配,您可以使用更少的迭代, 并跳到下一个不匹配项目的索引。

当剩下的物品少于您找到的最大物品时,您也可以退出。

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];

<强> maxRepeats(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开始

答案 9 :(得分:0)

不幸的是,由于缺乏声誉,我无法发表评论所以我会将此作为答案发布。对于我的任务Robbie Averill's solution是完美的,但它包含一个小错误。我有一个由2个值组成的数组 - 0&amp; 1.5,但上面提到的代码只计算&#34; 1.5&#34;价值虽然我有&#34; 0&#34;在更高的条纹中重复。问题是价值在这里没有进行严格的比较:

if(temp != '' && temp == arr[i]) {

并且修复很简单:if(temp !== '' && temp == arr[i]) {

我已使用此修复程序更新了Robbie的jsfiddler:http://jsfiddle.net/d5X2k/5/

答案 10 :(得分:0)

不幸的是,一个问题被标记为重复,但它与此问题不同。所以我必须在这里回答,对不起......

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));

这是一个比减少更慢的解决方案,你可以看到:

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));

答案 11 :(得分:0)

输入数组:

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)))

使用regexp的替代方法( spoiler:〜25%,比使用reduce()的解决方案慢。请参见下面的“使用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