28

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

3
  • 2
    Efficient in what way? Commented Nov 7, 2015 at 0:16
  • I should have been more clear on that. I just meant in a concise way, nothing about memory efficiency Commented Nov 7, 2015 at 0:18
  • What do you expect to happen in case of multiple arrays with maximum length? Commented Aug 14, 2019 at 13:21

10 Answers 10

38

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);
Sign up to request clarification or add additional context in comments.

Comments

17

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

4 Comments

condition would be a[p].length > c.length ? p : i
This is the most elegant answer I have seen for this question.
Yeah this is a much nicer answer. Could even ditch the index usage for a direct reference. collection.reduce((a, b) => (a.length > b.length ? a : b),[]);
It's nice but it doesn't work if one of your arrays is empty
6

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)

2 Comments

idx + 1 looks too suspicious. No way it is correct =)
@vp_arth - yep :) I don't remember why I wrote it like that, but I re-wrote the answer after your comment. Thanks for letting me know!
3

masterArray.reduce(function(a,i,ii){
  if (ii === 1){
    return a
  };
  if (i.length > a.length){
    return i
  }
  return a
})

1 Comment

This returns the longest array, not its index.
1

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]

Comments

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

Comments

0

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'.

jsfiddle: https://jsfiddle.net/mckinleymedia/8xo5ywbc/

1 Comment

I like @Downgoat's solution better.
0

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>

Comments

-1

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

Comments

-1

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)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.