Найти индекс самого длинного массива в массиве массивов

Если у вас есть массив, содержащий неопределенное количество массивов

Пример:

var masterArray = [ [1,2,3,4,5],
                    [1,2], 
                    [1,1,1,1,2,2,2,2,4,4],
                    [1,2,3,4,5] ];

Каков эффективный способ найти индекс самого длинного массива в masterArray? (в этом примере индекс будет 2).

Ответ 1

var masterArray = [ [1,2,3,4,5],
                    [1,2], 
                    [1,1,1,1,2,2,2,2,4,4],
                    [1,2,3,4,5] ];

Однострочный:

masterArray.map(function(a){return a.length;}).indexOf(Math.max.apply(Math, masterArray.map(function(a){return a.length;})));

Но лучше кэшировать результаты map.

var lengths = masterArray.map(function(a){return a.length;});
lengths.indexOf(Math.max.apply(Math, lengths));

Обратите внимание, что даже этот код перебирает массив 3 раза (map, max, indexOf отдельно).
Для более эффективного использования вы должны использовать ручной итерационный массив.

var max = -Infinity;
var index = -1;
masterArray.forEach(function(a, i){
  if (a.length>max) {
    max = a.length;
    index = i;
  }
});

Reduce метод:

masterArray.reduce(function(maxI,el,i,arr) {return el.length>arr[maxI].length ? i : maxI;}, 0)

Ответ 2

.reduce - .reduce способ сделать это:

masterArray.reduce(function (pending, cur, index, ar) { ar[ pending ].length > cur.length ? pending : index }, 0);

Или с ES6:

masterArray.reduce((p, c, i, a) => a[p].length > c.length ? p : i, 0);

Ответ 3

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

Ответ 4

Редуктор выполняет итерацию массива массивов, где аккумулятор представляет индекс самого длинного массива, начиная с индекса 0.

Для каждой итерации текущая длина элемента (который является массивом) сравнивается с длиной массива по индексу (аккумулятору) из списка массивов, и, если оно больше, аккумулятор увеличивается.

var arrays = [ 
  [1,1,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] 
]

var indexOfLongestArray = arrays.reduce((idx, arr) => 
  arr.length > arrays[idx].length ? idx + 1 : idx
, 0)


// print result:
console.log( indexOfLongestArray )

Ответ 5

Lazy UnderscoreJS:

_.max(masterArray, function(i){ return i.length; })

Ответ 6

Сортируйте список индексов по длине в порядке убывания и возьмите первый:

a.map((e, i) => i) . sort((i, j) => a[j].length - a[i].length) [0]

Ответ 7

Если вы используете Lodash (начиная с версии 4.0), вы можете легко использовать _.maxBy и _.size как iteratee:

_.maxBy(masterArray, _.size) -> [1, 1, 1, 1, 2, 2, 2, 2, 4, 4]

Чтобы найти минимальное использование _.minBy

_.minBy(masterArray, _.size) -> [1, 2]

Ответ 8

Я столкнулся с этим сегодня и нашел этот вопрос.

Вот более современный подход:

const longestArray = masterArray.reduce((acc, curr, index) =>
    curr.length > acc.length ? index : index - 1
);
  • теперь код находит индекс самого длинного массива, а не самого длинного массива (извините, неправильно прочитал вопрос).

Ответ 9

Вы можете перебирать все элементы внешнего массива с помощью цикла for и сравнивать длину каждого из своих элементов с самым длинным массивом, который вы нашли до сих пор.

Следующая функция возвращает индекс самого длинного массива или -1, если массив пуст.

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

Ответ 10

Попробуйте использовать цикл while

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

Ответ 11

Использование lodash:

_.max(_.map(masterArray, function(v, k) { return { id: k, size: v.length }; }),'size').id;

Это создает новый массив с объектами, имеющими "id" и "размер", затем находит максимальный размер в этом массиве и возвращает его "id".

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

Ответ 12

если порядок элементов в массиве для вас не имеет значения, и вы хотите просто использовать самый длинный массив, вы можете отсортировать массив по длине

      masterArray.sort((a, b) => b.length - a.length);
      const theLongest = masterArray[0];

в этом случае первый элемент всегда будет самым длинным