Ярлык вложенных циклов в Javascript?

#javascript

#javascript

Вопрос:

В программе, которую я пишу, у меня есть многомерный массив, и мне нужно выполнить некоторую операцию только над самыми внутренними объектами.

Есть ли лучший способ написать этот код?

 for (const threeDimensionalArray of fourDimensionalArray) {
  for (const twoDimensionalArray of threeDimensionalArray) {
    for (const oneDimensionalArray of twoDimensionalArray) {
      for (const obj of oneDimensionalArray) {
        // do something
      }
    }
  }
}
 

Что-то вроде:

 for (const obj someSpecialKeyword fourDimensionalArray) {
  // do something
}
 

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

Каков был бы наилучший подход здесь?

Комментарии:

1. Какова фактическая структура (т. Е. Формальный тип данных) массива? Я предполагаю, что это неровный массив (поскольку JavaScript не поддерживает истинные многомерные массивы).

2. Рассматривали ли вы возможность написания функции итератора?

3. Самый внутренний тип — это объект с атрибутами

4. flatMap Функция — это то, что я бы использовал, а затем перебирал все элементы, если производительность является ключевой… вы уверены, что хотите решить эту проблему с помощью JavaScript?

Ответ №1:

Я знаю одно решение, которое использует функцию выравнивания

Я предполагаю, что под «функцией выравнивания» вы подразумеваете функцию редуктора? (К сожалению, Array.prototype функции JavaScript, такие как reduce , map , filter и т. Д., Выполняют полные копии на каждом шаге).

Альтернативой является написание функции генератора (она же функция итератора):

 function* getAll( fourDimensionalArray ) { // The asterisk is not a typo.
    for (const threeDimensionalArray of fourDimensionalArray) {
        for (const twoDimensionalArray of threeDimensionalArray) {
            for (const oneDimensionalArray of twoDimensionalArray) {
                for (const obj of oneDimensionalArray) {
                    yield obj;
                }
            }
        }
    }
}
 

Используется так:

 for( const item of getAll( fourDimensionalArray ) ) {
    // do something
}
 

Функции генератора очень эффективны и не вызывают операцию копирования массива.

Комментарии:

1. благодаря вам я сегодня узнал кое-что новое; мой голос

Ответ №2:

Вы могли бы использовать рекурсивную функцию, которая принимает массив или элемент и обратный вызов для не массивов.

Эта функция не зависит от фиксированной структуры.

 function iter(value, cb) {
    if (Array.isArray(value)) {
        for (const item of value) iter(item, cb);
    } else {
        cb(value);
    }
}
 

Комментарии:

1. Рассмотрим const arr = []; arr.push( arr ); iter( arr, console.log );

2. «у этого массива нет этажа» — я не знаком с термином «этаж» в контексте массивов — можете ли вы объяснить? Я хотел сказать, что ваша функция уязвима для переполнения стека при работе с циклическим объектом-графом.

3. с технической точки зрения массив имеет циклическую ссылку и не может получить конечный элемент массива.