Функция получения глубины уровня вложенности массивов в массиве
function glubina(arr){ if(arr.filter(i => i.constructor.name === "Array").length != 0){ return 1 + glubina([].concat(...arr.filter(i => i.constructor.name === "Array"))); } else { return 0; } }
Та же функция, оформленная тернарным оператором
function glubina(arr){ return x <= arr.filter(i => i.constructor.name === "Array").length != 0 ? 1 + glubina([].concat(...arr.filter(i => i.constructor.name === "Array"))) : 0; }
Собственный метод для объектов-прототипов Array
Array.prototype.glubina = function(){ if(this.filter(i => i.constructor.name === "Array").length != 0){ return 1 + [].concat(...this.filter(i => i.constructor.name === "Array")).glubina(); } else { return 0; } }
Тот же метод, оформлен тернарным оператором
Array.prototype.glubina = function(){ return x <= this.filter(i => i.constructor.name === "Array").length != 0 ? 1 + [].concat(...this.filter(i => i.constructor.name === "Array")).glubina() : 0; }
Как работает функция?
Данная функция вызывает сама себя каждый раз пока не найдёт самый глубокий массив в основном массиве. Каждое «погружение» в глубину основного массива итерируется в возвращаемое значение.
Как только встречается глубокий массив без массивов в качестве элементов, тогда функция возвращает ноль и рекурсивные вызовы прекращаются. К этому моменту уже произошло суммирование итератора и его значение возвращается в числовом виде глубины основного массива.
В основе работы функции используется условие:
.filter(i => i.constructor.name === "Array").length != 0
На первой итерации мы проверяем основной массив на наличие в нём других массивов. Мы обращаемся к каждому элементу основного массива и проверяем его свойство .constructor и .name (имя конструктора). Это свойство возвращает нам строковое представление класса, в котором был создан объект текущей фильтрации.
Условно можно выделить такое деление:
- фигурные скобки принадлежат классу Object,
- квадратные скобки принадлежат классу Array,
- числа принадлежат классу Number
- строки принадлежат классу String
Если фильтр отберёт хоть что-то, значит в основном массиве есть другие массивы (представители класса Array). Поэтому мы сравниваем длину нового массива.
Когда это условие выполняется, тогда мы возвращаем «1» и прибавляем к этой единице новый вызов функции. В этот новый вызов мы передаём:
[].concat(...arr.filter(i => i.constructor.name === "Array"))
…передаём один новый массив, который получился в результате «склейки» элементов, где были массивы.
С этого момента начинается рекурсия. Вызовы будут продолжаться, пока в массивах будут встречаться другие массивы. Единичка будет приплюсовываться к другой единичке….и так, далее, до победного.
Пример работы — Скопируй, Потестируй!
Для тестов возьмём массивы:
var massiv1 = [1, 2, 3, [44, 44, [11,11]], 5, 6, [77, 77], [[ [ [ [] ] ] ]]]; var massiv2 = [1, 2, 3, [44, 44, [11,11]], 5, 6, [77, 77]]; var massiv3 = [1, 2, 3, [44, 44], 5, 6, [77, 77]]; var massiv4 = [1, 2, 3, 5, 6]; var massiv5 = []; var massiv6 = [,,,];
Вызовем каждый функцию по каждому массиву:
glubina(massiv1); glubina(massiv2); glubina(massiv3); glubina(massiv4); glubina(massiv5); glubina(massiv6);
Способ № 2 — через строки и квадратные скобки
Можно взглянуть на задачу поиска глубины массива по другому. Например можно говорить о массиве как о строке. То есть на первом шаге этой логики мы преобразуем массив в строку.
Пусть у нас будет массив:
var massiv = [1, [2, 22, [222, [ 2222]]], 3, 4, 5, 6, [66, [666,,,,,[6666]]], 7, 8]
Мы воспользуемся встроенным конструктором JSON и его методом stringify()
var s1 = JSON.stringify(massiv)
В результате конвертации мы получим такую строку:
"[1,[2,22,[222,[2222]]],3,4,5,6,[66,[666,null,null,null,null,[6666]]],7,8]"
Если подойти к решению задачи объективно, то нам вообще всё равно какие значения находятся внутри массива. То есть из этой строки мы можем безболезненно выбросить все значения и оставить только квадратные скобки. Нам даже запятые не нужны.
Сперва раскидываем каждый символ на элемент массива:
var m1 = [...s1]
Теперь новый массив выглядит так:
["[", "1", ",", "[", "2", ",", "2", "2", ",", "[", "2", "2", "2", ",", "[", "2", "2", "2", "2", "]", "]", "]", ",", "3", ",", "4", ",", "5", ",", "6", ",", "[", "6", "6", ",", "[", "6", "6", "6", ",", "n", "u", "l", "l", ",", "n", "u", "l", "l", ",", "n", "u", "l", "l", ",", "n", "u", "l", "l", ",", "[", "6", "6", "6", "6", "]", "]", "]", ",", "7", ",", "8", "]"]
Фильтруем этот массив по наличию левой и правой квадратной скобки. Напоминаю, что они в виде строки лежат в массиве:
var m2 = m1.filter(i=>(i=="[" || i=="]"))
Получаем отфильтрованный массив:
[ "[", "[", "[", "[", "]", "]", "]", "[", "[", "[", "]", "]", "]", "]" ]
Теперь собираем символы скобок в одну строку:
var s2 = m2.join("")
Получили такую строку:
"[[[[]]][[[]]]]"
Что мы видим? Теперь нашим ориентиром будет являться последовательное сочетание левой и правой скобки — []
Если мы будем удалять такие сочетания, то количество «удалений» будет равно глубине массива. То есть мы удаляем пары скобок и смотрим на строку заново. Если есть пары, то снова удаляем. А в это время у нас будет счётчик прибавляться на 1 каждый раз.
Сделаем это через цикл for и регулярные выражения:
counter=-1; for(s="[[[[]]][[[]]]]"; s.length != 0; counter++){ s = s.replace(/\[\]/g, ""); }
Почему мы взяли счётчик со стартовым значением -1? Дело в том, что JSON преобразовал наш массив с «внешними границами» в виде левой и правой квадратными скобками. В строке они будут лишними и поэтому счётчик «как бы не будет учитывать последнее извлечение».
Давайте по шагам посмотрим о чём идёт речь:
s="[[[[]]][[[]]]]" s = s.replace(/\[\]/g, "") "[[[]][[]]]" s = s.replace(/\[\]/g, "") "[[][]]" s = s.replace(/\[\]/g, "") "[]" s = s.replace(/\[\]/g, "") ""
Строка «опустошилась» за 4 (четыре) вызова замены. Но если мы посмотрим на исходный массив, то в нём максимальная глубина вложенности равна 3 (трём).
Поэтому счётчик стартует с -1.
Функция нахождения глубины массива через строки и квадратные скобки
function glubinaMassiva (arr){ counter=-1; for(s=[...JSON.stringify(arr)].filter(i=>(i=="[" || i=="]")).join(""); s.length != 0; counter++){ s = s.replace(/\[\]/g, ""); } return counter; } или function glubinaMassiva (arr){ for(counter=-1, s=[...JSON.stringify(arr)].filter(i=>(i=="[" || i=="]")).join(""); s.length != 0; counter++){ s = s.replace(/\[\]/g, ""); } return counter; }
Скрин из VSC
Пример для теста:
glubinaMassiva([[[[[[[[[]]]]]]]],[[[[[[[]]]]]]]]) 8
Информационные ссылки
JavaScript | Как узнать глубину каждого элемента массива?
JavaScript | Как вытащить элементы массивов в массивах на один уровень?