webDevleoper101
webDevleoper101

Reputation: 69

Transform a object of arrays into an array of objects with javascript

I have a large object of arrays. I need to break down this object into an array of objects. I believe that underscore.js is good tool for this type of object transformation, but I’ve never used that library before. For this example I need to convert the key of each property to a ‘name’ variable in the output array, and than push elements of each property of each object into array's. That’s difficult to explain so below I have a before and after array to help visualize what I’m trying to accomplish. Can I accomplish this task with underscore.js easier than pure javascript ? I’ve attempted this with for loops and if else statements but it got messy quickly, so any help is greatly appreciated.

Before:

var obj = {
    "AH5T5TAFXX-001": 
        ["AH5T5TAFXX-001",
        {
            Bin_reads:2436307,
            IC_lot:1,
            LabChip_size_bp:410,
            LibType:"RNA",
            Tot_reads:7386376,
            bioSple:193,
            internal_controls:5
        }, {
            Bin_reads:2906003,
            IC_lot:1,
            LabChip_size_bp:395,
            LibType:"RNA",
            Tot_reads:6680167,
            bioSple:198,
            internal_controls:5
        }],
    "AH5NVVAFXX-002":
        ["AH5NVVAFXX-002",
        {   
            Bin_reads:2436307,
            IC_lot:1,
            LabChip_size_bp:410,
            LibType:"RNA",
            Tot_reads:7386376,
            bioSple:193,
            internal_controls:5
        },
        {   
            Bin_reads:2436307,
            IC_lot:1,
            LabChip_size_bp:410,
            LibType:"RNA",
            Tot_reads:6680167,
            bioSple:193,
            internal_controls:5
        }]
};

After:

var arr = [
    {
        "name": "AH5T5TAFXX-001",
        "Bin_reads": [2436307,2906003],
        "IC_lot": [1,1],
        "LabChip_size_bp": [410,395],
        "LibType": ["RNA", "RNA"],
        "Tot_reads": [7386376,6680167]
        "bioSple": [193,198],
        "internal_controls": [5,5]
    },{
        "name": "AH5T5TAFXX-002",
        "Bin_reads": [2436307,2906003],
        "IC_lot": [1,1],
        "LabChip_size_bp": [410,395],
        "LibType": ["RNA", "RNA"],
        "Tot_reads": [7386376,6680167]
        "bioSple": [193,198],
        "internal_controls": [5,5]
    }
];

Upvotes: 0

Views: 775

Answers (4)

le_m
le_m

Reputation: 20228

The following is a robust method to flatten your data structure and merge the individual entries. It is agnostic to the number and order of entries:

var result = Object.keys(obj).map((key, index) => {
  var entries = obj[key];
  var combined = {};
  entries.forEach(entry => {
    if (typeof entry === 'string') {
       combined.name = entry;
    } else {
      Object.keys(entry).forEach(key => {
        if (Array.isArray(combined[key])) {
          combined[key].push(entry[key]);
        } else {
          combined[key] = [entry[key]];
        }
      });
    }
  });
  return combined;
})

var obj = {
    "AH5T5TAFXX-001": 
        ["AH5T5TAFXX-001",
        {
            Bin_reads:2436307,
            IC_lot:1,
            LabChip_size_bp:410,
            LibType:"RNA",
            Tot_reads:7386376,
            bioSple:193,
            internal_controls:5
        }, {
            Bin_reads:2906003,
            IC_lot:1,
            LabChip_size_bp:395,
            LibType:"RNA",
            Tot_reads:6680167,
            bioSple:198,
            internal_controls:5
        }],
    "AH5NVVAFXX-002":
        ["AH5NVVAFXX-002",
        {   
            Bin_reads:2436307,
            IC_lot:1,
            LabChip_size_bp:410,
            LibType:"RNA",
            Tot_reads:7386376,
            bioSple:193,
            internal_controls:5
        },
        {   
            Bin_reads:2436307,
            IC_lot:1,
            LabChip_size_bp:410,
            LibType:"RNA",
            Tot_reads:6680167,
            bioSple:193,
            internal_controls:5
        }]
};

var result = Object.keys(obj).map((key, index) => {
  var entries = obj[key];
  var combined = {};
  entries.forEach(entry => {
    if (typeof entry === 'string') {
      combined.name = entry;
    } else {
      Object.keys(entry).forEach(key => {
        if (Array.isArray(combined[key])) {
          combined[key].push(entry[key]);
        } else {
          combined[key] = [entry[key]];
        }
      });
    }
  });
  return combined;
})

console.log(result);

Upvotes: 1

pishpish
pishpish

Reputation: 2614

// iterate through the keys of 'obj'
// create an array element for each key
console.log( Object.keys(obj).map( function(key){ 

  // 'result' is the element to be returned for each key
  // every property value of 'obj' is an array
  // whose first element represents the name of the new object
  var result = {
    'name': obj[key][0]
  };
  if( obj[key].length > 1 ){
      // pull all attribute names of second element of array
      // and set them to empty arrays in the transformed object
      var properties = Object.keys( obj[key][1] );
      properties.forEach( function( prop ){ result[prop] = []; } );

      // iterate through the input array (skipping the first element)
      // and add a value to the matching array of 'result' 
      for( var i=1; i<obj[key].length; i++ )
        properties.forEach( function( prop ){ result[prop].push( obj[key][i][prop] ); } );
    }
    return result;

}) );

Upvotes: 1

akinuri
akinuri

Reputation: 12027

In a very very straight forward way, it'd look like this:

// output array
var arr = [];

// iterating the "obj" object
for (prop1 in obj) {

    // temporary object
    var newObj = {
        // setting the property name
        name : prop1,
    };

    // iterating the array of objects
    // skipping the first item. it is a string
    for (var i = 1; i < obj[prop1].length; i++) {

        // iterating the object that's inside the array
        for (prop2 in obj[prop1][i]) {

            // checking if the new property already exists in the new obj
            // if not, create it
            if (!newObj[prop2]) {
                newObj[prop2] = [];
            }

            // adding the values from the two objects into an array in a single object
            newObj[prop2].push(obj[prop1][i][prop2]);
        }
    }
    arr.push(newObj);
}

console.log(JSON.stringify(arr, false, "\t")) outputs

[
    {
        "name": "AH5T5TAFXX-001",
        "Bin_reads": [
            2436307,
            2906003
        ],
        "IC_lot": [
            1,
            1
        ],
        "LabChip_size_bp": [
            410,
            395
        ],
        "LibType": [
            "RNA",
            "RNA"
        ],
        "Tot_reads": [
            7386376,
            6680167
        ],
        "bioSple": [
            193,
            198
        ],
        "internal_controls": [
            5,
            5
        ]
    },
    {
        "name": "AH5NVVAFXX-002",
        "Bin_reads": [
            2436307,
            2436307
        ],
        "IC_lot": [
            1,
            1
        ],
        "LabChip_size_bp": [
            410,
            410
        ],
        "LibType": [
            "RNA",
            "RNA"
        ],
        "Tot_reads": [
            7386376,
            6680167
        ],
        "bioSple": [
            193,
            193
        ],
        "internal_controls": [
            5,
            5
        ]
    }
]

Upvotes: 0

BryanGrezeszak
BryanGrezeszak

Reputation: 577

This function:

function solution(A)
{
    var result = [];
    for (var key in A)
    {
        var subArr = A[key];

        var newObj = {};
        result.push(newObj);
        newObj.name = key;

        for (var i=1, ii=subArr.length; i<ii; i++)
        {
            var subSubObj = subArr[i];
            for (var subSubKey in subSubObj)
            {
                if (!newObj[subSubKey])
                    newObj[subSubKey] = [subSubObj[subSubKey]];
                else
                    newObj[subSubKey].push(subSubObj[subSubKey]);
            }
        }
    }

    return result;
}

will return this object if given your input:

[
    {
        "name": "AH5T5TAFXX-001",
        "Bin_reads": [2436307,2906003],
        "IC_lot": [1,1],
        "LabChip_size_bp": [410,395],
        "LibType": ["RNA","RNA"],
        "Tot_reads": [7386376,6680167],
        "bioSple": [193,198],
        "internal_controls": [5,5]
    },
    {
        "name": "AH5NVVAFXX-002",
        "Bin_reads": [2436307,2436307],
        "IC_lot": [1,1],
        "LabChip_size_bp": [410,410],
        "LibType": ["RNA","RNA"],
        "Tot_reads": [7386376,6680167],
        "bioSple": [193,193],
        "internal_controls": [5,5]
    }
]

JSFiddle example (logs to console, so open dev tools): https://jsfiddle.net/mpey5wfv/

Upvotes: 0

Related Questions