Как извлечь несколько столбцов из двухмерного массива?

#javascript #arrays #multidimensional-array

#javascript #массивы #многомерный массив

Вопрос:

Могу ли я получить некоторые рекомендации о том, как извлечь несколько столбцов из двумерного массива, подобного приведенному ниже, используя JavaScript?

 Array = [
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12],
];
  

простые методы, которые я видел до сих пор, используя forEach или map, позволят извлекать по ОДНОМУ столбцу за раз, есть ли способ вложить его каким-либо образом, чтобы извлечь индекс любого столбца, который вы пожелаете?

Допустим, столбец вывода desire равен 1,2 и 4.

 Output = [
  [1, 2, 4],
  [5, 6, 8],
  [9,10,12],
];
  

Редактировать:

Еще одна проблема, которую мне нужно решить, заключается в том, как удалить строку, если она Array [i] [1] = 0 или пуста.

Допустим, у нас есть дополнительные элементы массива…

 Array = [
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12],
  [13,0,15,16],
  [17, ,19,20],
  [21,22,23,24],
]; 
  

Желаемый результат получен сейчас…

 Output = [
  [1, 2, 4],
  [5, 6, 8],
  [9,10,12],
  [21,22,24],
]; 
  

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

1. я понятия не имею, чего вы хотите достичь, не могли бы вы добавить выходные данные вашего желания?

2. Можете ли вы показать пример желаемого результата, а также как вы будете указывать, какие столбцы вы хотите извлечь?

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

4. Вы можете использовать параметр index, подобный . array.map(элемент, индекс, массив)

Ответ №1:

Вы можете .map() каждую строку из arr преобразовать в новый массив, который вы можете получить, используя inner .map() для массива столбцов / индексов, которые вы хотите получить. Внутренняя карта сопоставит каждый индекс с соответствующим значением из строки, предоставляя вам значения в каждом столбце для каждой строки.

Смотрите пример ниже:

 const arr = [
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12],
];

const cols = [1, 2, 4];
const res = arr.map(r => cols.map(i => r[i-1]));
console.log(res);  

Дополнительная информация: Как вы упомянули, первая карта предоставляет каждый внутренний массив внутри arr функции внутреннего отображения:

 cols.map(i => r[i-1])
  

Эта функция сопоставления будет перебирать индексы, определенные внутри cols , и преобразовывать их в новое значение. Например, допустим, you’re r — это второй массив:

 [5, 6, 7, 8]
  

Выполнение cols.map(...) приведет к циклическому перебору каждого элемента (обозначаемого i в функции обратного вызова) в [1, 2, 4] . Для каждого элемента мы «преобразуем» его в новый элемент:

 i = 1
r = [5, 6, 7, 8]
new value: r[1-1] = 5
  

На следующей итерации мы рассмотрим следующее значение в cols :

 i = 2
r = [5, 6, 7, 8]
new value: r[2-1] = 6
  

Наконец, мы смотрим на конечное значение в cols :

 i = 4
r = [5, 6, 7, 8]
new value: r[4-1] = 8
  

Таким образом, функция сопоставления создает новый массив, который преобразует значения из cols [1, 2, 4] в значения по тем индексам в текущей строке, которые должны быть [5, 6, 8] . Это происходит для каждого внутреннего массива / строки, что приводит к конечному результату.


РЕДАКТИРОВАТЬ В соответствии с вашим редактированием, вы можете применить ту же логику, что и выше, чтобы получить ваши массивы только с теми столбцами, которые вы хотите. После того, как вы это сделаете, вы можете использовать .filter() для сохранения только тех строк, которые имеют истинное значение во втором столбце. Сохранение всех массивов с истинными значениями во втором столбце приведет к удалению массивов с неистинными значениями во втором столбце (ложными значениями) из вашего результирующего массива. 0 и undefined оба являются изменяемыми значениями, поэтому они не сохраняются.

Смотрите пример ниже:

 const arr = [
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12],
  [13,0,15,16],
  [17, ,19,20],
  [21,22,23,24],
]

const cols = [1, 2, 4];
const col = 2;
const res = arr.filter(r => r[col-1]).map(r => cols.map(i => r[i-1]));
console.log(res);  

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

 const arr = [
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12],
  [13,0,15,16],
  [ ,17,19,20],
  [21,22,23,24],
]

const cols = [1, 2, 4];
const col = [1, 2];
const res = arr.filter(r => col.every(c => r[c-1])).map(r => cols.map(i => r[i-1]));
console.log(res);  

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

1. Работает великолепно!. Первая карта предоставляет доступ к каждому элементу в arr (r => cols.map(i => r[i-1])). Но точно, что происходит внутри этих скобок … немного за пределами моего понимания, можете ли вы помочь разработать, чтобы мы могли лучше понять, как это работает?

2. @user1488934 конечно, я пытался добавить еще несколько деталей. Короче говоря, внутренняя система .map() принимает значения из cols и обрабатывает их как индексы. Таким образом, для текущего массива r он сопоставит каждое значение индекса i из cols со значением в этом индексе из r

3. @Nick_Parsons, если нам теперь требуется фильтровать col 1, а также 2; const col = [1,2]; , как мы могли бы это реализовать? Я пробовал const res = arr.map(r => cols.map(i => r[i-1])).filter(r => r [col.map(i => r [i-1]) -1]); Также для большого набора данных, скажем, с 30 столбцами и более 5000 строк; будет ли фильтр перед отображением более выгодным с точки зрения производительности?

4. Я обновил свой ответ (см. Последний скрытый фрагмент кода). Производительность для него будет N * M N * K, где N = размер arr , M = размер cols , K = размер col . Если сначала выполнить фильтрацию, то производительность составит N * K X * M, где X = размер массива после фильтра. В худшем случае фильтр не удалит из вашего массива никаких элементов arr , которые в этом случае X = N. Итак, вы правы. Выполнение фильтра перед отображением будет более производительным, так как X обычно будет меньше N , что делает N * K X * M <= N * M N * K (таким образом, в принципе, использование filter перед отображением было бы более производительным)

Ответ №2:

Вы можете подойти к этому следующим образом. Решение заключается в использовании параметра index, доступного в методе filter .

Array.filter(currElem, индекс, массив)

Поскольку массив проиндексирован на 0, я создал массив с нужным вам индексом в данных как [0,1,3] . Вам нужно передать массив данных и массив индексов в функцию.

 var array = [
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12],
];

var arrIndex = [0,1,3];

function extractData(arr,indexArr) {

  return arr.map(obj => {  
      return obj.filter((ob,index) => {
          if(indexArr.includes(index)){return ob}
      })
  })
}

console.log(extractData(array,arrIndex));