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);
asked Jan 19, 2016 at 21:15
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]);
answered Jan 19, 2016 at 21:37
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>';

answered Jan 19, 2016 at 21:23

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

answered Jan 19, 2016 at 21:22

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

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.