javascriptarrayses6-proxy

Multiple Access to two-dimensional array (using setters/getter via Proxy or Object.defineProperty)


I have a two dimensional array that I need to perform read and write action on from various angles. Sometimes I need to get/set a single row (easy of course) and sometimes I need to get/set a single column or even just a single cell but coming from a column perspective.

Let me try to explain what I want to achieve:

function myFunction() {

  var myArray = [['a1','b1'],['a1','b1']];

  var ds = new DataStructure(myArray);
  console.log(ds) // -> [['a1','b1'],['a1','b1']]

  console.log(da[0]) // -> ['a1','b1']
  console.log(da[1]) // -> ['a2','b2']

  console.log(da.cols[0]) // -> ['a1','a2']
  console.log(da.cols[1]) // -> ['b1','b2']
  da.cols[0] = ['A1','A2']
  console.log(da.cols[0]) // -> ['A1','A2']
  da.cols[1][1] = 'Q2'
  console.log(da.cols[1]) // -> ['b1','Q2']

  console.log(ds) // -> [['A1','b1'],['A1','Q1']]

  console.log(myArray) // -> [['A1','b1'],['A1','Q1']]
}

So basically I want to have a wrapper to my original data structure and all get/set access to it should work directly on the original structure (by reference I reckon).

Any idea?

I have tried to use Proxy() and Object.defineProperty() to define custom getters/setters. It kind of works but as soon as I access into a column i.e. ds.cols[0][0] it doesn't work anymore.


Solution

  • You need create custom class which will encapsulate and expose setter and getters set/get values specified rows and columns.

    In the below example refer the how values being set/get in myFunction method.

    Refer the below example:

    class DataStructure {
      constructor(array) {
        this.array = array;
        this.cols = new Proxy({}, this.getColumnHandler());
      }
    
      getColumnHandler() {
        return {
          get: (target, prop) => {
            if (typeof prop === 'symbol') return target[prop];
            const colIndex = Number(prop);
            if (isNaN(colIndex)) return undefined;
            return this.array.map(row => row[colIndex]);
          },
          set: (target, prop, value) => {
            const colIndex = Number(prop);
            if (isNaN(colIndex)) return false;
            value.forEach((val, rowIndex) => {
              if (this.array[rowIndex]) {
                this.array[rowIndex][colIndex] = val;
              }
            });
            return true;
          }
        };
      }
    
      getRow(rowIndex) { // Get row by index
        return this.array[rowIndex];
      }
    
      setRow(rowIndex, row) {
        this.array[rowIndex] = row;
      }
    
      getCell(rowIndex, colIndex) { // Get cell by row index and column index
        return this.array[rowIndex][colIndex];
      }
    
      setCell(rowIndex, colIndex, value) { Set cell by row index and column index
        this.array[rowIndex][colIndex] = value;
      }
    }
    
    
    function myFunction() {
      var myArray = [['a1', 'b1'], ['a2', 'b2']];
      var ds = new DataStructure(myArray);
      ds.cols[0] = ['A4', 'A2']; // Set column by index 
      ds.setRow(0,['A9', 'A0']) // Set row by index 
      ds.setCell(1,1,'Q2'); // Set cell by column and row 
      return ds;
    }
    
    console.log(JSON.stringify(myFunction));