0

I have an array like this:

var products = [
    ['date1','prod1',1,2],
    ['date2','prod2',3,4],
    ['date3','prod3',5,6],
    ['date4','prod4',7,8],
    ['date5','prod5',9,0]
];

And need to pull the integers out of the array and format it like this:

var newProductsArray = [[1,3,5,7,9],[2,4,6,8,0]];

It needs to be able to be dynamic and expand because the products array will have more "columns".

I have this code but it's doing it backwards and can't figure out how to loop through and just break up the arrays. I am sure it's something simple I'm missing.

var metricStartPosition = 2;
var dataSetInnerArray = [];
var dataSetArray = [];

for (var i = 0; i < array.length; i++) {
    for (var k = metricStartPosition; k < array[i].length; k++) {
        dataSetInnerArray.push(array[i][k]);
    };
    dataSetArray.push(dataSetInnerArray);
    dataSetInnerArray = [];
}; 
miceana
  • 3
  • 1
  • 1
    *"...in a different order..."* - But your results has the values in the same order as in the original array. When you talk about expanding to cater for more columns, do you mean that the items might be like `['date1','prod1',1,2,'a','b']` and thus your output array would have one nested array per column from the input? Will every item in the input always have the same number of columns as the other items? – nnnnnn Jul 09 '16 at 02:23

4 Answers4

2

You can do something like this:

var products = [
      ['date1','prod1',1,2,'a','b'],
      ['date2','prod2',3,4,'c','d'],
      ['date3','prod3',5,6,'e','f'],
      ['date4','prod4',7,8,'g','h'],
      ['date5','prod5',9,0,'i','j']
];
var metricStartPosition = 2;
var newProductsArray = products.reduce(function(output, item) {
  item.slice(metricStartPosition).forEach(function(v, i) {
    (output[i] || (output[i] = [])).push(v);
  });
  return output;
}, []);
console.log(JSON.stringify(newProductsArray));

Should work with any number of columns.

Of course you could use nested .forEach() loops or old-school nested for loops instead of .forEach() inside .reduce().

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
  • Nice use of reduce. – ZombieCode Jul 09 '16 at 02:43
  • @ZombieCode - Thanks. In this case I admit `.reduce()` doesn't really give you much of a benefit compared to setting `newProductsArray = [];` before a nested `.forEach()` loop that adds to `newProductsArray` directly, but of course once you start using `.reduce()` you tend to want to use it for *everything*, and this way does feel a little more self-contained. – nnnnnn Jul 09 '16 at 02:46
1

If I got your question correctly, inverting the order of the two for loops will do it:

var metricStartPosition = 2;
var dataSetInnerArray = [];
var dataSetArray = [];

for (var k = metricStartPosition; k < products[0].length; k++) {
     for (var i = 0; i < products.length; i++) {

        dataSetInnerArray.push(products[i][k]);
    };
    dataSetArray.push(dataSetInnerArray);
    dataSetInnerArray = [];
};
GCSDC
  • 3,138
  • 3
  • 28
  • 48
0

Related Post

This should flip the array.

var newArray = array[0].map(function(col, i) { 
  return array.map(function(row) { 
    return row[i] 
  })
});

As a function this is:

function foo (array) {
    var newArray = array[0].map(function(col, i) { 
        return array.map(function(row) { 
            return row[i] 
        })
    });
    return newArray;
}

By flip the array I mean this:

1 2 3      1 4 7
4 5 6  ->  2 5 8
7 8 9      3 6 9

And in your case:

var products = [
    ['date1','prod1',1,2],
    ['date2','prod2',3,4],
    ['date3','prod3',5,6],
    ['date4','prod4',7,8],
    ['date5','prod5',9,0]
];

var newProducts = [
    ['date1','date2','date3','date4','date5'],
    ['prod1','prod2','prod3','prod4','prod5'],
    [1,3,5,7,9],
    [2,4,6,8,0]
];
Community
  • 1
  • 1
Will Hamic
  • 672
  • 4
  • 20
0

You could try and index all the columns one-by-one (assuming all the rows of the data is of the same types column-wise:

arrayRow = products[0] //['date1','prod1',1,2]
newProductsArray = [];
intIndices = [];
arrayRow.forEach(function(data, i) {
  if (typeof(data) === 'number')
    intIndices.push(i);
});

// intIndices should be [2, 3]

and then iterate through the whole products array to get all the columns:

intIndices.forEach(function (colIndex) {
  innerArray = [];
  for (var i = 0; i < products.length; i++) {
    innerArray.push(products[i][colIndex]);
  }
  newProductsArray.push(innerArray);
});

// you should get nested arrays with all the integer columns
// [ [ 1, 3, 5, 7, 9 ],
//   [ 2, 4, 6, 8, 0 ] ]