Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.

Join them; it only takes a minute:

Sign up
Join the Stack Overflow community to:
  1. Ask programming questions
  2. Answer and help your peers
  3. Get recognized for your expertise

I have json that looks like this (copied from dev tools inspector)

salePurchases
  salesPeriods: Array[2]
    0: Object
      data: Array[5]
        0: Object
        1: Object
        2: Object
        3: Object
        4: Object
      period: "2011"
    1: Object
      data: Array[5]
        0: Object
        1: Object
        2: Object
        3: Object
        4: Object
      period: "2012"

  purchasePeriods: Array[2]
    0: Object
      data: Array[5]
        0: Object
        1: Object
        2: Object
        3: Object
        4: Object
      period: "2011"
    2: Object
      data: Array[5]
        0: Object
        1: Object
        2: Object
        3: Object
        4: Object
      period: "2012"

I want to pull it apart and make it creat a new object that looks like this -

OrderedByYears:
  2011:
    data: Array[10]
      0: Object // this should be the 1st item from the salesPeriods array with a period of 2011
      1: Object // this should be the 1st item from the purchasePeriods array with a period of 2011
      2: Object
      3: Object
      4: Object
      5: Object
      6: Object
      7: Object
      8: Object
      9: Object  // this should be the 5th item from the salesPeriods array with a period of 2011
      10: Object // this should be the 5th item from the purchasePeriods array with a period of 2011
  2012:
    data: Array[10]
      0: Object // this should be the 1st item from the salesPeriods array with a period of 2012
      1: Object // this should be the 1st item from the purchasePeriods array with a period of 2012
      2: Object
      3: Object
      4: Object
      5: Object
      6: Object
      7: Object
      8: Object
      9: Object // this should be the 5th item from the salesPeriods array with a period of 2012
      10: Object // this should be the 5th item from the purchasePeriods array with a period of 2012

I'm basing the arrangement by the key 'period' and then alternating between joining each array together but alternating between the relavant object salesPeriods and purchasePeriods.

I'm sure this is relatively simple using underscore. Anyone know if it's an easy thing to do? Explaining the steps involved would be much appreciated.

share|improve this question
    
Assuming you're stuck and this is not just a 'write this code for me' question - where are you stuck? – Benjamin Gruenbaum Jul 23 '13 at 17:23
    
I'm stuck on the approach I should take, I'm going to try John's answer below now. – Finnnn Jul 23 '13 at 17:25
up vote 0 down vote accepted

I haven't used underscore.js, but it looks like it maps nicely to the general concepts. Here is the general approach you would want:

  1. concat the salesPeriods and purchasePeriods together into one list.
  2. groupBy the period value in each of the objects.
  3. map the grouped results into the object shape you want.

You might want to throw some sort statements in there, depending upon your goals.

share|improve this answer
    
Amazing, thanks very much. I think I've achieved what I wanted without the need to map. Excuse my ignorance, but what are the benefits of mapping> – Finnnn Jul 23 '13 at 17:32
    
@Finnnn: Care to share your solution? – Scott Sauyet Jul 23 '13 at 18:05
    
@Finnnn: Mapping is just the common method for restructuring an object. Sometimes you can use other methods to alter the objects, but that's more of a side effect rather than the actual intent of the function. So, I listed map in order to make the process clear. – John Fisher Jul 23 '13 at 18:39
    
@Finnnn: And since your target output is a plain object, indexed by the year, you might consider one additional step after a map: a reduce (also known as a fold), which is a technique for combining a list of items into a single output. – Scott Sauyet Jul 23 '13 at 18:45

I know you have an approach that's working for you. I've been working on a Functional Programming Library in Javascript, and this is how I would handle the problem with that library:

var weave = compose(flatten, zip);
reduce(function(obj, period) {
    obj[period.year] = {data: period.data};
    return obj;
}, {}, map(function(year) {
    var getMatch = find(function(period) {return period.period === year;});
    return {year: year, data: weave(getMatch(salePurchases.salesPeriods).data, 
                                    getMatch(salePurchases.purchasePeriods).data)};
}, pluck("period", salePurchases.salesPeriods)));

Equivalents to all of the core functions used are also available in Underscore, although in most cases, the parameter order is different. So with Underscore you could do it like this:

var weave = _.compose(_.flatten, _.zip);
_.reduce(_.map(_.pluck(salePurchases.salesPeriods, "period"), function(year) {
    var getMatch = function(period) {return period.period === year;}
    return {year: year, data: weave(_.find(salePurchases.salesPeriods, getMatch).data, 
                                    _.find(salePurchases.purchasePeriods, getMatch).data)};
}), function(obj, period) {
    obj[period.year] = {data: period.data};
    return obj;
}, {});

You can see this in action with Ramda or with Underscore on JSFiddle.

The main idea is that I would start with a list of years, plucked off the salesPeriods. (This is assuming your data is representative, and all years needed would appear in both lists, and also that the sales periods and purchase periods are both comprehensive.) Then, using map, I would weave together the salesPeriod and purchase periods for each year, returning an object with a year, and an array of intermingled data. To turn this into your expected output, I would reduce this list, by assigning the relevant year property of a new object to an object whose data property was that intermingled data.

This technique allows for little error-checking along the way, but is quite compact.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.