1

I have data in the format

[
  {
    "timeline_map": {
      "2017-05-06": 770,
      "2017-05-07": 760,
      "2017-05-08": 1250
         ...
    }
  },
  {
    "timeline_map": {
      "2017-05-06": 590,
      "2017-05-07": 210,
      "2017-05-08": 300
         ...
    }
  },
  {
    "timeline_map": {
      "2017-05-06": 890,
      "2017-05-07": 2200,
      "2017-05-08": 1032
         ...
    }
  }
]

that in order to use in a google chart I need to change to the format

[
  ["2017-05-06", 770, 590, 890, ...],
  ["2017-05-07", 760, 210, 2200, ...],
  ["2017-05-08", 1250, 300, 1032, ...]
]

I wrote the following to make the transformation

let mapped = _.map(
  chartData.results[0].timeline_map, (timestampVal, timestampKey) => (
  [timestampKey].concat(
    _.map(
      chartData.results, lineData => (
        lineData.timeline_map[timestampKey]
        )
      )
    )
  )
)

This works, but I'm thinking that nesting the maps is not a good idea because how it will increase the amount of looping by the square off the length of the array being mapped. Is there a better way to achieve the desired result here.

JSBIN

5
  • ["2017-05-06": 770, 590, 890, ...] this is no valid JS. Either [["2017-05-06", ...], ["2017-05-07", ...]] or {"2017-05-06": [...], "2017-05-07": [...]}. Wich one is it? Commented Jun 6, 2017 at 19:30
  • @Thomas it's just an ellipsis to indicate there's more dates. The linked JSBIN doesn't have any pseudo elements like that Commented Jun 6, 2017 at 19:31
  • I'm not talking about the ellipsis, I'm talking about the : Commented Jun 6, 2017 at 19:32
  • @Thomas Ah. Oops. Corrected. Thanks! Commented Jun 6, 2017 at 19:36
  • Single dimensional array of objects. Commented Jun 6, 2017 at 19:46

2 Answers 2

4

You could use a closure over a hash table and assign the values accordingly to the date keys.

var data = [{ timeline_map: { "2017-05-06": 770, "2017-05-07": 760, "2017-05-08": 1250 } }, { timeline_map: { "2017-05-06": 590, "2017-05-07": 210, "2017-05-08": 300 } }, { timeline_map: { "2017-05-06": 890, "2017-05-07": 2200, "2017-05-08": 1032 } }],
    grouped = data.reduce(function (hash) {
        return function (r, o) {
            Object.keys(o.timeline_map).forEach(function (k) {
                if (!hash[k]) {
                    hash[k] = [k];
                    r.push(hash[k]);
                }
                hash[k].push(o.timeline_map[k]);
            });
            return r;
        };
    }(Object.create(null)), []);

console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

11 Comments

This is the right way to go but requires just one step further to give the desired result.
@Redu, do you know the wanted result? o_O
the parameters are supplied by the reduce method.
These? (Object.create(null)), [])?
Object.create(null) initialize hash in the closure. the empty array is the start value of the result array.
|
2

Merge the objects using _.mergeWith(), and then _.map() the resulting object to an array of arrays:

const arr = [{
    "timeline_map": {
      "2017-05-06": 770,
      "2017-05-07": 760,
      "2017-05-08": 1250
    }
  },
  {
    "timeline_map": {
      "2017-05-06": 590,
      "2017-05-07": 210,
      "2017-05-08": 300
    }
  },
  {
    "timeline_map": {
      "2017-05-06": 890,
      "2017-05-07": 2200,
      "2017-05-08": 1032
    }
  }
];

const result = _.map(_.mergeWith({}, ...arr, (o1, o2) => {
  if(Array.isArray(o1)) {
    o1.push(o2)
    return o1;
  }
  
  if(_.isNumber(o2)) {
    return [o2];
  }
}).timeline_map, (v, k) => [k, ...v]);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

1 Comment

+1 for nice clean solution. Just pointing out that spread operator will start giving call stack overflow error after array reaches a certain size.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.