Home Ask Login Register

Developers Planet

Your answer is one click away!

Mike S. February 2016

underscore - transform an array with _.map()

I have a multi-dimensional array of objects that I need to transform into a different array. I'm convinced that _.map() is what I need. Not having used it before, I'm having trouble traversing the array to extract the correct values. Given this simplified example:

[
   {
      "08/25/2015":[
         {
            "source":"someSource0",
            "name":"someName0",
            "stuff":"-6.728479",
            "stuffValue":"14.862200",
            "amount":"-100.00"
         },
         {
            "notNeeded0":-100,
            "subtotal":"-100.00"
         }
      ]
   },
   {
      "08/26/2015":[
         {
            "source":"someSource1",
            "name":"someName1",
            "stuff":"-9.496676",
            "stuffValue":"10.530000",
            "amount":"-100.00"
         },
         {
            "notNeeded0":-100,
            "subtotal":"-100.00"
         }
      ]
   },
   {
      "08/27/2015":[
         {
            "source":"someSource2",
            "name":"someName2",
            "stuff":"-9.469697",
            "stuffValue":"10.560000",
            "amount":"-100.00"
         },
         {
            "notNeeded0":-100,
            "subtotal":"-100.00"
         }
      ]
   },
   {
      "08/28/2015":[
         {
            "source":"someSource3",
            "name":"someName3",
            "stuff":"-1.731841",
            "stuffValue":"10.570000",
            "amount":"-18.24"
         },
         {
            "source":"someSource4",
            "name":"someName4",
            "stuff":"-2.628939",
            "stuffValue":"31.100000",
            "amount":"-81.76"
         },
         {
            "notNeeded0":-100,
            "subtotal":"-100.00"
         }
      ]
   },
   {
      "notNeeded1":-400,
      "notNeeded2":"-400.00"
   }
]

I needed to transform it to something structured like this:

[
   {
      "date":"08/27/2015",
      "detail":[
         {
                    

Answers


Aprillion February 2016

using built-in .filter, .map and .splice:

var modified = original.filter(function only_nested_arrays(obj) {
  var keys = Object.keys(obj)
  return keys.length === 1 && Array.isArray(obj[keys[0]])
}).map(function transform(obj) {
  var date = Object.keys(obj)[0],
      inner_array = obj[date],
      subtotal = inner_array.splice(-1)[0].subtotal
  inner_array.forEach(function(obj_inner) {
    obj_inner.subtotal = subtotal
  })
  return {date: date, detail: inner_array}
})

console.log(JSON.stringify(modified, null, 2))

But watch out for browser compatibility (see the links for a polyfill to make it work on IE8 or lower). Runnable code that alerts the result if you want to test:

"use strict"
var original = [
  {
    "08/25/2015":[
      {
        "source":"someSource0",
        "name":"someName0",
        "stuff":"-6.728479",
        "stuffValue":"14.862200",
        "amount":"-100.00"
      },
      {
        "notNeeded0":-100,
        "subtotal":"-100.00"
      }
    ]
  },
  {
    "08/26/2015":[
      {
        "source":"someSource1",
        "name":"someName1",
        "stuff":"-9.496676",
        "stuffValue":"10.530000",
        "amount":"-100.00"
      },
      {
        "notNeeded0":-100,
        "subtotal":"-100.00"
      }
    ]
  },
  {
    "08/27/2015":[
      {
        "source":"someSource2",
        "name":"someName2",
        "stuff":"-9. 


Ashwin February 2016

Using _.filter, _.map & _.chain here is what it would look like.

var transformed = _.chain(data).filter(function (obj) {
    var keys = _.keys(obj);
    // only allow where obj has only one key & the value is an array
    // consider replacing this with a check to see if the key is a date which should be more appropriate
    return keys.length === 1 && _.isArray(obj[keys[0]]);
}).map(function (obj) {
    var date     = _.keys(obj)[0];
    var details  = obj[date];
    var subtotal = details.splice(-1)[0].subtotal; // get the last obj from array destructively
    details      = _.map(details, function (detail) {
        detail.subtotal = subtotal; // append the subtotal to all the remaining detail objects
        return detail
    });
    return {
        date   : date,
        details: details
    }
}).value();

I'd suggest that you use the native functions as shown in Aprillion's answer so that you can avoid the whole chain() & then value() usages for getting the actual value from the wrapped object. You can use underscore when the requirements are a bit more complicated.

Post Status

Asked in February 2016
Viewed 1,200 times
Voted 14
Answered 2 times

Search




Leave an answer


Quote of the day: live life

Devs Planet ®

2014-2016 www.devsplanet.com

Devs Planet © all rights reserved

Search