2

I have the following data :

[
    {"date":1900,"data":[
        {"name":"Blackbird","value":0},
        {"name":"Seagull","value":1},
        {"name":"Sparrow","value":0}
    ]},
    {"date":1910,"data":[
        {"name":"Owl","value":1}
    ]},
    {"date":1920,"data":[
        {"name":"Eagle","value":0},
        {"name":"Albatross","value":2}
    ]}
]

I need to make an incremental array of arrays from it. It should look something like this :

[
    [
        {"name":"Blackbird","value":0,"date":1900},
        {"name":"Seagull","value":1,"date":1900},
        {"name":"Sparrow","value":0,"date":1900}
    ],
    [
        {"name":"Blackbird","value":0,"date":1910},
        {"name":"Seagull","value":1,"date":1910},
        {"name":"Sparrow","value":0,"date":1910},
        {"name":"Owl","value":1,"date":1910}
    ],
    [  
        {"name":"Blackbird","value":0,"date":1920},
        {"name":"Seagull","value":1,"date":1920},
        {"name":"Sparrow","value":0,"date":1920},
        {"name":"Owl","value":1,"date":1920},
        {"name":"Eagle","value":0,"date":1920},
        {"name":"Albatross","value":2,"date":1920}
    ]
]

No matter what I have tried, I always end up with all the dates I add to the objects being equal to the last value (1920 here). I understand that the objects are copied by reference only. I have tried using array.map() (like in the answer given here, but my question was not formulated right), but I still get the same problem.

EDIT Here's one example of code I've tried :

        var temp = [];
        var b = data.map(function(c, index, main) {
            var year = c.date;
            temp = [];
            main.slice(0, index + 1).map(function(d){
                var t = d.data.map(function(e){
                    e.date = year;
                    return e;
                });
                temp = temp.concat(t);
            });
            return temp;
        });
        console.log(b);
2
  • 3
    Please show the code you've tried. Commented Jan 19, 2016 at 21:18
  • since there's only 2-3 props, just make a new object via a literal on each iteration. something like {name: o.name, value: o.value, date: x.date} Commented Jan 19, 2016 at 21:23

3 Answers 3

1

Here's a working example:

You need to clone the object in order to "break" the reference.

var data = [
        {
          "date":1900,
           "data":[
            {"name":"Blackbird","value":0},
            {"name":"Seagull","value":1},
            {"name":"Sparrow","value":0}
          ]
        },
        {
          "date":1910,
          "data":[
            {"name":"Owl","value":1}
          ]
        },
        {
          "date":1920,
          "data":[
            {"name":"Eagle","value":0},
            {"name":"Albatross","value":2}
          ]
        }
    ];

    var incremental = [];
    var dataHistory = null;

    for(i = 0; i < data.length; i++){
      var temp = dataHistory ? dataHistory.slice() : []; //.slice to clone array

      //Replace all values with current date.
      for(var j = 0; j < temp.length; j++){
        temp[j] = JSON.parse(JSON.stringify(temp[j])); //Clone object
        temp[j].date = data[i].date;
      }
      
      //Add current date to object.
      for(var j = 0; j < data[i].data.length; j++){
         var aux = {
           name: data[i].data[j].name,
           value: data[i].data[j].value,
           date: data[i].date
         };
        
         temp.push(aux);
      }
      
      dataHistory = temp;
      incremental.push(temp);
    }

document.body.innerHTML = '<pre>' + JSON.stringify(incremental, null, 4) + '</pre>';

If you're using jQuery you can replace:

temp[j] = JSON.parse(JSON.stringify(temp[j]));

With:

temp[j] = $.extend({}, temp[j]);
Sign up to request clarification or add additional context in comments.

3 Comments

This seems to work, though x should be replaced by data, right ?
I have solved my problem using your trick with JSON.parse and JSON.stringify in the code sample I provided (on temp.concat(t) ).
Glad it helped, It's an easy, cross browser way to clone an object ;)
0

Try this one:

var data = [
    {"date":1900,"data":[
        {"name":"Blackbird","value":0},
        {"name":"Seagull","value":1},
        {"name":"Sparrow","value":0}
    ]},
    {"date":1910,"data":[
        {"name":"Owl","value":1}
    ]},
    {"date":1920,"data":[
        {"name":"Eagle","value":0},
        {"name":"Albatross","value":2}
    ]}
];

var result = data.map(function(item) {
  var replacement = [];
  for (var key in item.data) {
     var subItem = item.data[key];
     subItem.date = item.date;
     replacement.push(subItem); 
  }
  return replacement;
});

document.body.innerHTML = '<pre>' + JSON.stringify(result, null, 3) + '</pre>';

Comments

0

Use map, iterate over the inner array, and set the date property to each object etc.

var data = [
    {"date":1900,"data":[
        {"name":"Blackbird","value":0},
        {"name":"Seagull","value":1},
        {"name":"Sparrow","value":0}
    ]},
    {"date":1910,"data":[
        {"name":"Owl","value":1}
    ]},
    {"date":1920,"data":[
        {"name":"Eagle","value":0},
        {"name":"Albatross","value":2}
    ]}
]

data = data.map(function(obj, i, arr) {
    var o = [];
    
    arr.slice(0, i).forEach(function(item) {
        item.data.forEach(function(data) {
            o.push(Object.assign({}, data))
        });
    });
    
    return o.concat(obj.data.map(function(item) { item.date = obj.date; return item }));
});

document.body.innerHTML = '<pre>' + JSON.stringify(data, null, 4) + '</pre>';

Object.assign with polyfill

2 Comments

It adds the date to the objects, but doesn't create an "incremental" array.
Oh, you want to add the previous arrays as you go as well. Just map it again and slice and return

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.