Find the index of the longest array in an array of arrays
If you have an array containing an indefinite amount of arrays
ex:
var masterArray = [ [1,2,3,4,5],
[1,2],
[1,1,1,1,2,2,2,2,4,4],
[1,2,3,4,5] ];
What is an efficient way to find the index of the longest array in masterArray? (in this example index would be 2).
One-liner is:
masterArray
.map(a=>a.length)
.indexOf(Math.max(...masterArray.map(a=>a.length)));
But better to cache masterArray.map(a=>a.length)
results.
const lengths = masterArray.map(a=>a.length);
lengths.indexOf(Math.max(...lengths));
Note, this code still iterate array at least* 3 times(map
, max
, indexOf
separately).
*Spread operator is for readability and can be omitted
For more efficiency you should manual iterate array.
let max = -Infinity;
let index = -1;
masterArray.forEach(function(a, i){
if (a.length > max) {
max = a.length;
index = i;
}
});
Reduce
method:
masterArray.reduce((maxI,el,i,arr) =>
(el.length>arr[maxI].length) ? i : maxI, 0);
.reduce
is the nicest way to do this:
masterArray.reduce(function (pending, cur, index, ar) { ar[ pending ].length > cur.length ? pending : index }, 0);
Or with ES6:
masterArray.reduce((p, c, i, a) => a[p].length > c.length ? p : i, 0);
A reducer iterates the array of arrays, where the accumulator represents the index of the longest array, starting with index 0
.
For each iteration, the current item’s (array) length
is compared to the length
of the currently longest array found (arrays[acc]
) and if greater, the accumulator is set to that index
.
var arrays = [
[1,1,1,1,1],
[1,1],
[1,1,1,1,1,1,1,1], // ⬅ The longest, which is at index 2
[1,1,1,1],
[1,1,1,1,1,1]
]
var indexOfLongestArray = arrays.reduce((acc, arr, idx) => {
console.log(acc, idx, JSON.stringify([arr, arrays[acc]]))
return arr.length > arrays[acc].length ? idx : acc
}, 0)
// print result:
console.log( "longest array is at index: ", indexOfLongestArray )
Short function:
var indexOfLongestArray = list => list.reduce((a, arr, idx) =>
arr.length > arrays[a].length ? idx : a
, 0)
masterArray.reduce(function(a,i,ii){
if (ii === 1){
return a
};
if (i.length > a.length){
return i
}
return a
})
Sort a list of indexes by length in descending order, and take the first one:
a.map((e, i) => i) . sort((i, j) => a[j].length - a[i].length) [0]
You can iterate over all entries of the outer array using a for
loop and compare the length of each of its items to the longest array you have found so far.
The following function returns the index of the longest array or -1
if the array is empty.
function indexOfLongest(arrays) {
var longest = -1;
for (var i = 0; i < arrays.length; i++) {
if (longest == -1 || arrays[i].length > arrays[longest].length) {
longest = i;
}
}
return longest;
}
var masterArray = [ [1,2,3,4,5],
[1,2],
[1,1,1,1,2,2,2,2,4,4],
[1,2,3,4,5] ];
document.write(indexOfLongest(masterArray));
Using lodash:
_.max(_.map(masterArray, function(v, k) { return { id: k, size: v.length }; }),'size').id;
This creates a new array with objects having ‘id’ and ‘size’, then finds the maximum size in that array, and returns its ‘id’.
using lodash _.maxBy
let a = [[1,2,3,4],[1,3,2,33,3,3,3,32,2,3,31,1],[1]]
console.log(_.maxBy(a, i=>i.length))
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
Try using while
loop
var masterArray = [
[1, 2, 3, 4, 5],
[1, 2],
[1, 1, 1, 1, 2, 2, 2, 2, 4, 4],
[1, 2, 3, 4, 5]
];
var i = 0, len = masterArray.length;
while (i < len) {
// if array[i + 1] exists
// and array[i + 1] length greater than array[i] length
// and i + 1 equals array length - 1
// break
if (masterArray[i + 1]
&& masterArray[i + 1].length < masterArray[i].length
&& i + 1 === len - 1) {
break
}
// else increment i
else {
++i
}
}
console.log(masterArray[i])
an elementary and didactic solution
var masterArray = [ [1,2,3,4,5],
[1,2],
[1,1,1,1,2,2,2,2,4,4],
[1,2,3,4,5] ];
let maxIndex = -1
let currMax = 0;
for (const i in masterArray) {
if (masterArray[i].length > currMax) {
currMax = masterArray[i].length
maxIndex = i
}
}
console.log(maxIndex)