Rafa Guillermo
Rafa Guillermo

Reputation: 15367

How to extract columns from a 2D array?

Scenario:

I have a 2 Dimensional array consisting of values, for example:

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

The number of rows can vary, though will always be a multiple of two.

Question:

How can I extract columns out of this array using .map() so that I can get sub-arrays each containing two columns?

Example:

// columns 1 and 2:
ext1 = [ [ 1, 2 ],
         [ 7, 8 ],
         [ 3, 4 ],
         [ 9, 0 ] ];

// columns 3 and 4:
ext2 = [ [ 3, 4 ],
         [ 9, 0 ],
         [ 5, 6 ],
         [ 1, 2 ] ];

// columns 5 and 6:
ext3 = [ [ 5, 6 ],
         [ 1, 2 ],
         [ 7, 8 ],
         [ 3, 4 ] ];

Upvotes: 4

Views: 3760

Answers (5)

Stuart
Stuart

Reputation: 9858

You can make a function like this that selects columns based on an array of indices:

const getColumns = (arr, indices) => arr.map(row => indices.map(i => row[i]));
getColumns(arr, [0, 1]);    // returns the first two columns

If the ultimate aim is to split the array into equal size chunks you could do it like this:

const splitIntoColumnGroups = (arr, width) => 
  [...Array(Math.ceil(arr[0].length/width)).keys()].map(i => 
    arr.map(row => 
      row.slice(i * width, (i + 1) * width)));

Upvotes: 7

Alan Omar
Alan Omar

Reputation: 4217

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


const columns = (arr,cols) => arr.map(e => e.slice(...cols))

console.log(columns(arr,[0,2])) 
console.log(columns(arr,[1,4])) 

Upvotes: 2

Md Sabbir Alam
Md Sabbir Alam

Reputation: 5054

If you really want to use map you can do this,

const arr = [ [ 1, 2, 3, 4, 5, 6],
              [ 7, 8, 9, 0, 1, 2],
              [ 3, 4, 5, 6, 7, 8],
              [ 9, 0, 1, 2, 3, 4] ];
const prev = {}; 
arr.map((curr) => {
  let counter = 1;
  while(curr.length > 0) {
    let splittedArr = curr.splice(0, 2);
    if(prev[`ext${counter}`]) {
     prev[`ext${counter}`] = [...prev[`ext${counter}`], splittedArr] 
    } else {
      prev[`ext${counter}`] = [splittedArr] 
    }
    counter++;
  }
});
console.log(prev);

But you can do the following using reduce,

 const arr = [ [ 1, 2, 3, 4, 5, 6],
              [ 7, 8, 9, 0, 1, 2],
              [ 3, 4, 5, 6, 7, 8],
              [ 9, 0, 1, 2, 3, 4] ];
const res = arr.reduce((prev, curr) => {
  let counter = 1;
  while(curr.length > 0) {
    let splittedArr = curr.splice(0, 2);
    if(prev[`ext${counter}`]) {
     prev[`ext${counter}`] = [...prev[`ext${counter}`], splittedArr] 
    } else {
      prev[`ext${counter}`] = [splittedArr] 
    }
    counter++;
  }
  return prev;
}, {});
console.log(res);

Upvotes: 0

Nenad Vracar
Nenad Vracar

Reputation: 122047

You could do this with reduce and forEach method and inside you can check if the remainder is 0 and then add current and next element to the current column.

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

const columns = arr.reduce((r, a, i) => {
  let col = 0;

  a.forEach((e, j) => {
    if (!r[col] && a[j + 1]) r[col] = []
    if (j % 2 == 0) {
      r[col].push([e, a[i + 1]])
      col++
    }
  })

  return r;
}, [])

console.log(columns)

Upvotes: 1

Tatranskymedved
Tatranskymedved

Reputation: 4371

You can do it with using map and filter as:

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

function fn(array, firstIndex, secondIndex) {
    return array.map(a => a.filter((b,i) => i == firstIndex || i == secondIndex));
}

var result = fn(arr, 2, 3);
console.log(result);

Upvotes: 3

Related Questions