Javascript-获取数组中数组最大和的最佳方法

时间:2018-08-06 09:14:02

标签: javascript arrays

我有以下数组:

   arr = [
     [ 1, 1, 1, 1, 1, 1, 1 ],
     [ 1, 1, 0, 0, 1, 1, 0 ],
     [ 1, 0, 0, 0, 1, 0, 0 ],
     [ 0, 0, 0, 0, 0, 0, 0 ],
     [ 0, 1, 0, 1, 0, 0, 2 ],
     [ 1, 0, 0, 1, 0, 2, 4 ],
     [ 0, 0, 0, 0, 2, 4, 4 ],
     [ 0, 0, 0, 0, 4, 4, 0 ],
     [ 1, 1, 1, 0, 0, 0, 0 ],
     [ 1, 1, 0, 2, 0, 0, 2 ],
     [ 1, 0, 0, 4, 0, 2, 0 ],
     [ 0, 0, 0, 4, 2, 0, 0 ],
     [ 0, 0, 2, 0, 0, 0, 1 ],
     [ 0, 2, 4, 0, 0, 1, 2 ],
     [ 2, 4, 4, 2, 1, 2, 4 ],
     [ 4, 4, 0, 0, 2, 4, 0 ]
  ]

当前,我在arr中获得了最大数组和,即19,像这样

   function getMaxSum(arr) {
      return arr.map(e => e.reduce((a, b) => a + b, 0)).sort((a,b) => a - b)[arr.length - 1];
   }
  • 我需要知道有没有更好的方法来实现这一目标?
  • 我正在使用原始数组的数组长度来获取结果数组的最后一个元素,因为在这种情况下,原始数组的长度与结果数组的长度相同。如果情况不同,那么如何在这里使用结果数组的长度:

    返回arr.map(e => e.reduce((a,b)=> a + b,0))。sort((a,b)=> a-b)[ 这里 -1];

2 个答案:

答案 0 :(得分:4)

这不是一个很大的改进,但是将值散布到Math.max

const data = [
     [ 1, 1, 1, 1, 1, 1, 1 ],
     [ 1, 1, 0, 0, 1, 1, 0 ],
     [ 1, 0, 0, 0, 1, 0, 0 ],
     [ 0, 0, 0, 0, 0, 0, 0 ],
     [ 0, 1, 0, 1, 0, 0, 2 ],
     [ 1, 0, 0, 1, 0, 2, 4 ],
     [ 0, 0, 0, 0, 2, 4, 4 ],
     [ 0, 0, 0, 0, 4, 4, 0 ],
     [ 1, 1, 1, 0, 0, 0, 0 ],
     [ 1, 1, 0, 2, 0, 0, 2 ],
     [ 1, 0, 0, 4, 0, 2, 0 ],
     [ 0, 0, 0, 4, 2, 0, 0 ],
     [ 0, 0, 2, 0, 0, 0, 1 ],
     [ 0, 2, 4, 0, 0, 1, 2 ],
     [ 2, 4, 4, 2, 1, 2, 4 ],
     [ 4, 4, 0, 0, 2, 4, 0 ]
  ]

function getMaxSum(arr) {
  return Math.max(...arr.map(e => e.reduce((a, b) => a + b, 0)))
}

console.log(getMaxSum(data))


@Rajesh指出,Math.max比那种更快:

const numbers = Array(10000).fill().map((x,i)=>i);

const max = numbersIn => Math.max(...numbersIn);
const getMaxViaSort = numbersIn => numbersIn
  .sort((a, b) => a > b ? -1 : 1)[0]

console.time('max');
max(numbers);
console.timeEnd('max');

console.time('max via sort');
getMaxViaSort(numbers);
console.timeEnd('max via sort');

答案 1 :(得分:2)

最佳策略应该是我们需要最少与数组互动的策略。

在我的方法中,我分别测试阵列产品,并将其与循环中的变量进行比较。这样,我无需运行新的隐式循环即可让Math.max再次检查我的所有条目,从而提高速度。

这也节省了内存管理,因为我不需要为Math.max映射并返回新的结果数组。

在循环结束时,我只是返回变量。

var data = [
    [1, 1, 1, 1, 1, 1, 1],
    [1, 1, 0, 0, 1, 1, 0],
    [1, 0, 0, 0, 1, 0, 0],
    [0, 0, 0, 0, 0, 0, 0],
    [0, 1, 0, 1, 0, 0, 2],
    [1, 0, 0, 1, 0, 2, 4],
    [0, 0, 0, 0, 2, 4, 4],
    [0, 0, 0, 0, 4, 4, 0],
    [1, 1, 1, 0, 0, 0, 0],
    [1, 1, 0, 2, 0, 0, 2],
    [1, 0, 0, 4, 0, 2, 0],
    [0, 0, 0, 4, 2, 0, 0],
    [0, 0, 2, 0, 0, 0, 1],
    [0, 2, 4, 0, 0, 1, 2],
    [2, 4, 4, 2, 1, 2, 4],
    [4, 4, 0, 0, 2, 4, 0]
];
function getMaxSum1(arr) {
    //The original method
    return arr.map(function (e) { return e.reduce(function (a, b) { return a + b; }, 0); }).sort(function (a, b) { return a - b; })[arr.length - 1];
}
function getMaxSum2(arr) {
    //From https://stackoverflow.com/a/51704254/5242739
    return Math.max.apply(Math, arr.map(function (e) { return e.reduce(function (a, b) { return a + b; }, 0); }));
}
function sumArray(arr) {
    var val = 0;
    for (var index = 0; index < arr.length; index++) {
        val += val;
    }
    return val;
}
function getMaxSum3(arr) {
    //My method
    var max;
    for (var i = 0; i < arr.length; i++) {
        var val = sumArray(arr[i]);
        if (max === void 0 || val > max) {
            max = val;
        }
    }
    return max;
}
//TEST
//parameters
var runs = 10;
var tests = 100000;
//output area
var out = document.body.appendChild(document.createElement("pre"));
//test functions
function simulate1() {
    var t = tests;
    var dt = Date.now();
    while (t--) {
        getMaxSum1(data);
    }
    out.textContent += 'getMaxSum1 took: ' + (Date.now() - dt) + "ms\n";
    requestAnimationFrame(simulate2);
}
function simulate2() {
    var t = tests;
    var dt = Date.now();
    while (t--) {
        getMaxSum2(data);
    }
    out.textContent += 'getMaxSum2 took: ' + (Date.now() - dt) + "ms\n";
    requestAnimationFrame(simulate3);
}
function simulate3() {
    var t = tests;
    var dt = Date.now();
    while (t--) {
        getMaxSum3(data);
    }
    out.textContent += 'getMaxSum3 took: ' + (Date.now() - dt) + "ms\n\n";
    if (runs--) {
        requestAnimationFrame(simulate1);
    }
}
//start
simulate1();
pre {
  max-height: 200px;
  overflow-y: scroll;
  background-color: #eee;
}

我添加了OliverRadini's answer来比较相对速度提升。