HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Converting a list of lists to a list of objects

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
convertinglistobjectslists

Problem

I have some code that does what I want - it just doesn't feel correct for being done in JavaScript.

What it does is take data that is like this:

var data = [['Marker', 'sampleName1', 'sampleName2'],
     ['CCR4', 71.6, 83.4],
     ['CD27', 42.3, 76.2]];


And create a list of objects that looks like this (to use the plot.ly JavaScript library):

[{x:['CCR4', 'CD27'], y:[71.6,42.3], name: 'sampleName1'},
{x:['CCR4', 'CD27'], y:[83.4,76.2], name: 'sampleName2'}]


What I have is this:

var bData = [];
for (var i=0; i < data.length; i++) {
        var row = data[i];
        if (i ==0) {
                //Handle creation of objects
                for (var k = 1; k < row.length; k++) {
                        var obj = {name : row[k], type:'bar', x:[], y:[]};
                        bData.push(obj);
                }
        } else {
                var marker = row[0];
                for (var k=1; k < row.length; k++) {
                        var obj = bData[k -1];
                        obj.x.push(marker);
                        obj.y.push(row[k]);
                }
        }
}


What would be a better, more legible approach to this?

Solution

Here's a functional solution which I think is cleaner and makes what you are actually doing (essentially extracting columns from the data) more clear.

I put the explanation inline as comments:

function plotlyFormat(data) {
  var data = data.slice(0),         // make a copy
      headers = data.shift(),       // remove header row and save it
      x = column(data, 0);          // calculate the x property, same for all objects

  // Create the objects, each one's "y" data is just a column 
  // of the original data

  return headers.map(function(name, i) { 
    return {x: x, y: column(data,i), name: name}
  }).slice(1);  

  // ^^^ the final "slice(1) above removes the first record, 
  // since it's the "Marker" column, not an actual sample

  // simple utility function to extract a column from a nested array (matrix)
  function column(matrix, i) { return matrix.map(function(row) { return row[i] }) }
}


Just call the function on your input data, and it will return it in the format you want.

And an uncommented version, to see the character savings :)

function plotlyFormat(data) {
  var data = data.slice(0),
      headers = data.shift(),
      x = column(data, 0);

  return headers.map(function(name, i) { 
    return {x: x, y: column(data,i), name: name}
  }).slice(1);

  function column(matrix, i) { return matrix.map(function(row) { return row[i] }) }
}

Code Snippets

function plotlyFormat(data) {
  var data = data.slice(0),         // make a copy
      headers = data.shift(),       // remove header row and save it
      x = column(data, 0);          // calculate the x property, same for all objects

  // Create the objects, each one's "y" data is just a column 
  // of the original data

  return headers.map(function(name, i) { 
    return {x: x, y: column(data,i), name: name}
  }).slice(1);  

  // ^^^ the final "slice(1) above removes the first record, 
  // since it's the "Marker" column, not an actual sample

  // simple utility function to extract a column from a nested array (matrix)
  function column(matrix, i) { return matrix.map(function(row) { return row[i] }) }
}
function plotlyFormat(data) {
  var data = data.slice(0),
      headers = data.shift(),
      x = column(data, 0);

  return headers.map(function(name, i) { 
    return {x: x, y: column(data,i), name: name}
  }).slice(1);

  function column(matrix, i) { return matrix.map(function(row) { return row[i] }) }
}

Context

StackExchange Code Review Q#111365, answer score: 3

Revisions (0)

No revisions yet.