优化 javascript 代码以在数组中查找 3 个最大的元素及其索引?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11792158/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 14:21:10  来源:igfitidea点击:

Optimized javascript code to find 3 largest element and its indexes in array?

javascriptalgorithmsorting

提问by tilak

I need more optimized javascript code to find 3 largest element in array. I have tried with this code.

我需要更优化的 javascript 代码才能在数组中找到 3 个最大的元素。我已经尝试过使用此代码。

var maxIndex = new Array();
var maxPoints = new Array();
var scoreByPattern = new Array(93,17,56,91,98,33,9,38,55,78,29,81,60);

function findLargest3(){ 

      maxPoints[0]=0;
      maxPoints[1]=0;
      maxPoints[2]=0;
    for(i=0;i < scoreByPattern.length; i++){        
        if( scoreByPattern[i] > maxPoints[0]){                               
             maxPoints[0] = scoreByPattern[i];
             maxIndex[0]=i;   
        }


    }

    for(i=0;i < scoreByPattern.length; i++){        
        if( scoreByPattern[i] > maxPoints[1] && scoreByPattern[i]< maxPoints[0] ){                               
             maxPoints[1] = scoreByPattern[i];
             maxIndex[1]=i;   
        }            
    }

    for(i=0;i < scoreByPattern.length; i++){        
        if( scoreByPattern[i] > maxPoints[2] && scoreByPattern[i]< maxPoints[1] ){                               
             maxPoints[2] = scoreByPattern[i];
             maxIndex[2]=i;   
        }            
    }

alert(scoreByPattern+"/******/"+maxPoints[0]+"/"+maxPoints[1]+"/"+maxPoints[2]);
//alert(maxIndex);
}

how to optimized the above ? (I need indexes of largest numbers)Is any other easy methods to solve the problem ?

如何优化以上内容?(我需要最大数的索引)还有其他简单的方法可以解决这个问题吗?

采纳答案by Rory McCrossan

Sort the array descending, then get the first three elements of it:

将数组降序排序,然后得到它的前三个元素:

var maxPoints = new Array();
var scoreByPattern = new Array(93,17,56,91,98,33,9,38,55,78,29,81,60);

findLargest3();

function findLargest3(){
    // sort descending
    scoreByPattern.sort(function(a,b) {
        if (a < b) { return 1; }
        else if (a == b) { return 0; }
        else { return -1; }
    });

    alert(scoreByPattern+"/******/"+scoreByPattern[0]+"/"+scoreByPattern[1]+"/"+scoreByPattern[2]);
}

Example fiddle

示例小提琴

回答by huysentruitw

Modified version

修改版

I have modified my answer to make it more generic. It searches for the indices of the n largest numbers of elements in the array:

我已经修改了我的答案,使其更通用。它搜索数组中 n 个最大元素的索引:

var scoreByPattern = [93,255,17,56,91,98,33,9,38,55,78,29,81,60];

function findIndicesOfMax(inp, count) {
    var outp = [];
    for (var i = 0; i < inp.length; i++) {
        outp.push(i); // add index to output array
        if (outp.length > count) {
            outp.sort(function(a, b) { return inp[b] - inp[a]; }); // descending sort the output array
            outp.pop(); // remove the last index (index of smallest element in output array)
        }
    }
    return outp;
}

// show original array
console.log(scoreByPattern);

// get indices of 3 greatest elements
var indices = findIndicesOfMax(scoreByPattern, 3);
console.log(indices);

// show 3 greatest scores
for (var i = 0; i < indices.length; i++)
    console.log(scoreByPattern[indices[i]]);

Here is a jsFiddle

这是一个jsFiddle

回答by Christoph

Without sorting the huge array: Runs in O(n)considering the large array. Returns an array of array with [x,y]where xis the value and ythe index in the large array.

不排序大数组:在O(n)考虑大数组时运行。返回一个数组数组,[x,y]其中xy大数组中的值和索引。

var ar = [3,172,56,91,98,33,9,38,55,78,291,81,60];
console.log(`input is: ${ar}`);

function getMax(ar){
    if (ar.length < 3) return ar;
    var max = [[ar[0],0],[ar[1],1],[ar[2],2]],
        i,j;
    
    for (i = 3;i<ar.length;i++){
        for (j = 0;j<max.length;j++){
            if (ar[i] > max[j][0]){
                max[j] = [ar[i],i];
                if (j<2){
                    max.sort(function(a,b) { return a[0]-b[0]; });
                }
               break;            
            }
        }
    }
    return max;
}
result = getMax(ar);

console.log('output [number,index] is:');
console.log(result);

回答by René

The default javascript sort callback won't work well because it sorts in a lexicographical order. 10 would become before 5(because of the 1)

默认的 javascript 排序回调无法正常工作,因为它按字典顺序排序。10 会变成 5 之前(因为 1)

No credit to me but:

不相信我,但是:

my_array.sort(function(a,b) {
    return a-b;
});

回答by robert king

Assuming a fairly normal distribution, this should be fairly optimal:

假设一个相当正态分布,这应该是相当理想的:

var max_three, numbers = new Array(93,17,56,91,98,33,9,38,55,78,29,81,60);

max_three = (function (numbers) {
    var i, one, two, three;
    one = -9999;
    two = -9999;
    three = -9999;

    for (i = 0; i < numbers.length; i += 1) {
        num = numbers[i];
        if (num > three) {
            if (num >= two) {
                three = two;
                if (num >= one) {
                    two = one;
                    one = num;
                }
                else {
                    two = num;
                }
            }
            else {
                three = num;
            }
        }
    }

    return [one, two, three]

}(numbers))



document.write(max_three)???????

98,93,91

98,93,91

回答by Salvador Dali

The best way is to use a combination of sortand slice:

最好的方法是结合使用sortslice

This simple one liner will solve your problem.

这个简单的单衬将解决您的问题。

[1, -5, 2, 8, 17, 0, -2].sort(function(a, b){return b - a}).slice(0, 3)

So if you have an array and want to find N biggest values:

因此,如果您有一个数组并想找到 N 个最大值:

arr.sort(function(a, b){return b - a}).slice(0, n)

And for N smallest values:

对于 N 个最小值:

arr.sort(function(a, b){return a - b}).slice(0, n)

回答by Hunter

Here is an optimized solutionfor your problem without using sort or other complex array method :

这是针对您的问题的优化解决方案,无需使用排序或其他复杂数组方法:

var maxIndex = new Array();
var maxPoints = new Array();
var scoreByPattern = new Array(93,17,56,91,98,33,9,38,55,78,29,81,60);
function findTop3(n) {
 for (var i = 0; i < n.length; i ++) {
  if (i === 0) {
   maxPoints.push(n[i]);
   maxIndex.push(i);
  } else if (i === 1) {
   if (n[i] > maxPoints[0]) {
    maxPoints.push(maxPoints[0]);    
    maxPoints[0] = n[i];
    maxIndex.push(maxIndex[0]);
    maxIndex[0] = i;
   } else {
    maxPoints.push(n[i]);
    maxIndex.push(i);
   }
  } else if (i === 2) {
   if (n[i] > maxPoints[0]) {
    maxPoints.push(maxPoints[0]);
    maxPoints[1] = maxPoints[0];
    maxPoints[0] = n[i];
    maxIndex.push(maxIndex[0]);
    maxIndex[1] = maxIndex[0];
    maxIndex[0] = i;
    
   } else {
    if (n[i] > maxPoints[1]) {
     maxPoints.push(maxPoints[1]);
     maxPoints[1] = n[i];
     maxIndex.push(maxIndex[1]);
     maxIndex[1] = i;
    } else {
     maxPoints.push(n[i]);
     maxIndex.push(i);
    }
   }
  } else {
   if (n[i] > maxPoints[0]) {
    maxPoints[2] = maxPoints[1];
    maxPoints[1] = maxPoints[0];
    maxPoints[0] = n[i];
    maxIndex[2] = maxIndex[1];
    maxIndex[1] = maxIndex[0];
    maxIndex[0] = i;
   } else {
    if (n[i] > maxPoints[1]) {
     maxPoints[2] = maxPoints[1];
     maxPoints[1] = n[i];
     maxIndex[2] = maxIndex[1];
     maxIndex[1] = i;
    } else if(n[i] > maxPoints[2]) {
     maxPoints[2] = n[i];
     maxIndex[2] = i;
    }
   }
  }
 }
}
findTop3(scoreByPattern);
console.log('Top Elements: ', maxPoints);
console.log('With Index: ', maxIndex);

回答by Sani Singh Huttunen

Why don't you just sort it and take the first (or last if sorted in ascending order) three elements.

为什么不直接对它进行排序并取第一个(或最后一个,如果按升序排序)三个元素。

var maxPoints = new Array();
var scoreByPattern = new Array(93,17,56,91,98,33,9,38,55,78,29,81,60);
scoreByPattern.sort();
maxPoints[0] = scoreByPattern[scoreByPattern.length - 1];
maxPoints[1] = scoreByPattern[scoreByPattern.length - 2];
maxPoints[2] = scoreByPattern[scoreByPattern.length - 3];

Edit
If you need the indeces of the largest arrays you can make a copy which you sort and then find the indices in the original array:

编辑
如果您需要最大数组的 indeces,您可以制作一个副本进行排序,然后在原始数组中找到索引:

var scoreByPattern = new Array(93,17,56,91,98,33,9,38,55,78,29,81,60);

// Make a copy of the original array.
var maxPoints = scoreByPattern.slice();

// Sort in descending order.
maxPoints.sort(function(a, b) {
    if (a < b) { return 1; }
    else if (a == b) { return 0; }
    else { return -1; }

});

// Find the indices of the three largest elements in the original array.
var maxPointsIndices = new Array();
maxPointsIndices[0] = scoreByPattern.indexOf(maxPoints[0]);
maxPointsIndices[1] = scoreByPattern.indexOf(maxPoints[1]);
maxPointsIndices[2] = scoreByPattern.indexOf(maxPoints[2]);

Another approach to find the indices without sorting is this:

另一种无需排序即可找到索引的方法是:

var scoreByPattern = new Array(93,17,56,91,98,33,9,38,55,78,29,81,60);
var maxIndices = new Array(Number.MIN_VALUE, Number.MIN_VALUE, Number.MIN_VALUE);

for (var i = 0; i < scoreByPattern.length; i++) {
  if (maxIndices[0] < scoreByPattern[i]) {
    maxIndices[2] = maxIndices[1];
    maxIndices[1] = maxIndices[0];
    maxIndices[0] = scoreByPattern[i];
  }
  else if (maxIndices[1] < scoreByPattern[i]) {
    maxIndices[2] = maxIndices[1];
    maxIndices[1] = scoreByPattern[i];
  }
  else if (maxIndices[2] < scoreByPattern[i]) maxIndices[2] = scoreByPattern[i];
}

回答by nbrooks

http://jsfiddle.net/GGkSt/

http://jsfiddle.net/GGkSt/

var maxPoints = [];
var scoreByPattern = [93,17,56,91,98,33,9,38,55,78,29,81,60];

function cloneArray(array) {
    return array.map(function(i){ return i; });
}    
function max3(array) {
    return cloneArray(array).sort(function(a,b) { return b-a; }).slice(0,3);
}
function min3(array) {
     return cloneArray(array).sort(function(a,b) { return a-b; }).slice(0,3);
}

var array=scoreByPattern;
alert("Max:"+ max3(array)[0] +' '+max3(array)[1] +' '+max3(array)[2]);
alert("Min:"+ min3(array)[0] +' '+min3(array)[1] +' '+min3(array)[2]);

回答by Ulmasbek rakhmatullaev

function get3TopItems(arr) {
  return arr.sort((a, b) => b - a).slice(0, 3);
}