Converting Array of Objects into Array of Arrays - javascript

I am hoping somebody will point me in right direction here. I have an Array with number of objects that have Date, Set and Value as Properties.
I need to convert this on client side to an Array of Arrays where each member Array holds data like this: [ Date, Value of Set 0, Value of Set 1 ]
I'm looking for a solution that will work with any number of "Sets", which is the part that makes it complicated for me. Any proposed solution may require jQuery or some other javascript library set you use to get this done. I don't have a problem with that, let's just get it done. :)
Please refer to initial and end data sets below:
First one is with just two sets:
var data = [
{ Date: "2/10/2013", Set: 0, Value: 1 },
{ Date: "2/10/2013", Set: 1, Value: 0 },
{ Date: "2/11/2013", Set: 0, Value: 15 },
{ Date: "2/11/2013", Set: 1, Value: 8 },
{ Date: "2/12/2013", Set: 0, Value: 12 },
{ Date: "2/12/2013", Set: 1, Value: 11 },
{ Date: "2/13/2013", Set: 0, Value: 15 },
{ Date: "2/13/2013", Set: 1, Value: 19 },
{ Date: "2/14/2013", Set: 0, Value: 10 },
{ Date: "2/14/2013", Set: 1, Value: 20 }
];
var endData = [
[ "2/10/2013", 1, 0 ],
[ "2/11/2013", 15, 8 ],
[ "2/12/2013", 12, 11 ],
[ "2/13/2013", 15, 19 ],
[ "2/14/2013", 10, 20 ]
];
And here is an example of 3 sets.
So, for example if data was like this:
var data = [
{ Date: "2/10/2013", Set: 0, Value: 1 },
{ Date: "2/10/2013", Set: 1, Value: 2 },
{ Date: "2/10/2013", Set: 2, Value: 3 },
{ Date: "2/11/2013", Set: 0, Value: 10 },
{ Date: "2/11/2013", Set: 1, Value: 15 },
{ Date: "2/11/2013", Set: 2, Value: 20 }
];
Returned array would need to be like this:
var endData = [
[ "2/10/2013", 1, 2, 3 ],
[ "2/10/2013", 10, 15, 20 ]
];
Any pointers are appreciated.

Use a loop and a global dat variable to keep track of where you are in the list:
var endData=[], dat='', row=[];
for (var i=0; i<data.length; i++) {
var obj=data[i], val=obj.Value;
if (dat!=obj.Date) {
if (i) endData.push(row);
dat = obj.Date;
row = [dat, val];
} else {
row.push(val);
}
}
endData.push(row); // last one
http://jsfiddle.net/mblase75/rgJbq/

;(function() {
var data = [
{ Date: "2/10/2013", Set: 0, Value: 1 },
{ Date: "2/10/2013", Set: 1, Value: 0 },
{ Date: "2/11/2013", Set: 0, Value: 15 },
{ Date: "2/11/2013", Set: 1, Value: 8 },
{ Date: "2/12/2013", Set: 0, Value: 12 },
{ Date: "2/12/2013", Set: 1, Value: 11 },
{ Date: "2/13/2013", Set: 0, Value: 15 },
{ Date: "2/13/2013", Set: 1, Value: 19 },
{ Date: "2/14/2013", Set: 0, Value: 10 },
{ Date: "2/14/2013", Set: 1, Value: 20 }
];
var endData = {};
for (var i = 0; i < data.length; ++i) {
var date = data[i].Date;
if (endData[date] === undefined)
endData[date] = [];
endData[date].push(data[i].Value);
}
var finalData = [];
for (var ed in endData) {
var a = [ed];
for (var i = 0; i < endData[ed].length; ++i) {
a.push(endData[ed][i]);
}
finalData.push(a);
}
console.log(finalData);
})();
The output looks like:
var finalData = [
["2/10/2013", 1, 0],
["2/11/2013", 15, 8],
["2/12/2013", 12, 11],
["2/13/2013", 15, 19],
["2/14/2013", 10, 20]
];

var endData = [];
var indexes = {};
for(var i = 0, len = data.length; i < len; i++) {
if(indexes[data[i].Date] === undefined) {
indexes[data[i].Date] = endData.length;
endData.push([data[i].Date]);
}
endData[indexes[data[i].Date]][data[i].Set + 1] = data[i].Value;
}

Related

Sort array and SUM item counts [duplicate]

I have javascript array object as below. My need is to sum value base on seach id in the array object.
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
],
For example sum of value for id 1 is 10 + 30 + 25 + 20 = 85 , It may be something link linq but I'm not sure in javascript. Thanks for all answers.
You can use a combination of filter and reduce to get the result you want:
sumOfId = (id) => array.filter(i => i.id === id).reduce((a, b) => a + b.val, 0);
Usage:
const sumOf1 = sumOfId(1); //85
Reading material:
Array.prototype.filter
Array.prototype.reduce
A way to do it with a traditional for loop
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
];
var sums = {};
for (var i = 0; i < array.length; i++) {
var obj = array[i];
sums[obj.id] = sums[obj.id] === undefined ? 0 : sums[obj.id];
sums[obj.id] += parseInt(obj.val);
}
console.log(sums);
running example
You can use reduce() and findIndex()
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
];
let res = array.reduce((ac,a) => {
let ind = ac.findIndex(x => x.id === a.id);
ind === -1 ? ac.push(a) : ac[ind].val += a.val;
return ac;
},[])
console.log(res);
JS noob here ... I guess something like this should be here too :-)
let newArray = {}
array.forEach((e) => {
!newArray[e.id] && (newArray[e.id] = 0);
newArray[e.id] += e.val;
});
You can loop on the array and check the ids.
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
];
var sum = 0;
var id = 1;
$.each(array, function(index, object){
if (object.id == id) {
sum += object.val;
}
});
console.log(sum);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Using Array#reduce and Map you can get the sum for each id like so. This also uses destructuring to have quicker access to properties.
const data=[{id:1,val:10},{id:2,val:25},{id:3,val:20},{id:1,val:30},{id:1,val:25},{id:2,val:10},{id:1,val:20}];
const res = data.reduce((a,{id,val})=>{
return a.set(id, (a.get(id)||0) + val);
}, new Map())
console.log(res.get(1));
console.log(res.get(2));
If you wanted to output all the sums, then you need to use Array#from
const data=[{id:1,val:10},{id:2,val:25},{id:3,val:20},{id:1,val:30},{id:1,val:25},{id:2,val:10},{id:1,val:20}];
const res = Array.from(
data.reduce((a,{id,val})=>{
return a.set(id, (a.get(id)||0) + val);
}, new Map())
);
console.log(res);
If the format should be similar as to your original structure, you need to add a Array#map afterwards to transform it.
const data=[{id:1,val:10},{id:2,val:25},{id:3,val:20},{id:1,val:30},{id:1,val:25},{id:2,val:10},{id:1,val:20}];
const res = Array.from(
data.reduce((a,{id,val})=>{
return a.set(id, (a.get(id)||0) + val);
}, new Map())
).map(([id,sum])=>({id,sum}));
console.log(res);
You could take GroupBy from linq.js with a summing function.
var array = [{ id: 1, val: 10 }, { id: 2, val: 25 }, { id: 3, val: 20 }, { id: 1, val: 30 }, { id: 1, val: 25 }, { id: 2, val: 10 }, { id: 1, val: 20 }],
result = Enumerable
.From(array)
.GroupBy(null, null, "{ id: $.id, sum: $$.Sum('$.val') }", "$.id")
.ToArray();
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/linq.js"></script>
Here is another option, introducing an Array.prototype.sum helper:
Array.prototype.sum = function (init = 0, fn = obj => obj) {
if (typeof init === 'function') {
fn = init;
init = 0;
}
return this.reduce(
(acc, ...fnArgs) => acc + fn(...fnArgs),
init
);
};
// .sum usage examples
console.log(
// sum simple values
[1, 2, 3].sum(),
// sum simple values with initial value
[1, 2, 3].sum(10),
// sum objects
[{ a: 1 }, { a: 2 }, { a: 3 }].sum(obj => obj.a),
// sum objects with initial value
[{ a: 1 }, { a: 2 }, { a: 3 }].sum(10, obj => obj.a),
// sum custom combinations
[{ amount: 1, price: 2 }, { amount: 3, price: 4 }]
.sum(product => product.amount * product.price)
);
var array = [{ id: 1, val: 10 }, { id: 2, val: 25 }, { id: 3, val: 20 }, { id: 1, val: 30 }, { id: 1, val: 25 }, { id: 2, val: 10 }, { id: 1, val: 20 }];
// solutions
console.log(
array.filter(obj => obj.id === 1).sum(obj => obj.val),
array.filter(({id}) => id === 1).sum(({val}) => val),
array.sum(({id, val}) => id === 1 ? val : 0)
);
references:
Array.prototype.reduce
Array.prototype.filter
Arrow functions used in sum(obj => obj.val)
Object destructing assignment used in ({id}) => id === 1
Rest parameters used in (acc, ...fnArgs) => acc + fn(...fnArgs)
Conditional (ternary) operator used in id === 1 ? val : 0

Can't find the right index for the missing date

I am trying to generate missing values from missing dates in an obj array structure,
In below code I generate the missing values, but the dates are incorrect, can anyone point me towards a solution where I with the given index can generate the correct date from the preceding value
const obj= {
arr: [
{ num: 1, date: new Date("2020-11-13T16:23:57.460Z") },
{ num: 2, date: new Date("2020-11-14T20:19:42.186Z") },
{ num: 3, date: new Date("2020-11-15T14:58:09.203Z") },
{ num: 4, date: new Date("2020-11-16T18:55:38.491Z") },
// { num: 5, date: new Date("2020-11-17T23:40:55.084Z") },
// { num: 6, date: new Date("2020-11-18T03:44:49.573Z") },
// { num: 7, date: new Date("2020-11-19T03:44:49.573Z") },
{ num: 8, date: new Date("2020-11-20T03:44:49.573Z") },
{ num: 9, date: new Date("2020-11-21T03:44:49.573Z") },
{ num: 10, date: new Date("2020-11-22T03:44:49.573Z") },
{ num: 11, date: new Date("2020-11-23T03:44:49.573Z") },
]
}
function ensure_time_line(source) {
for (let index in source.timeline) {
let i = parseInt(index)
let src = get_item(source.timeline, i)
let next = get_item(source.timeline, i + 1)
let current_date = new Date(src.date);
current_date.setUTCHours(0, 0, 0, 0)
// console.log('rc',src)
if (next) {
// console.log(next)
let tomorrow = new Date(current_date.setDate(current_date.getDate() + 1));
let next_date = new Date(next.date);
next_date.setUTCHours(0, 0, 0, 0)
console.log(next_date, tomorrow, src.date)
if (tomorrow.getTime() === next_date.getTime()) {
continue;
}
let q = source.timeline.splice(i + 1, 0, {
num: src.num,
date: tomorrow
})
}
}
}
outputs
[ { num: 1, date: 2020-11-13T16:23:57.460Z },
{ num: 2, date: 2020-11-14T20:19:42.186Z },
{ num: 3, date: 2020-11-15T14:58:09.203Z },
{ num: 4, date: 2020-11-16T18:55:38.491Z },
{ num: 5, date: 2020-11-17T23:40:55.084Z },
{ num: 5, date: 2020-11-17T23:40:55.084Z },
{ num: 5, date: 2020-11-17T23:40:55.084Z },
{ num: 5, date: 2020-11-17T23:40:55.084Z },
{ num: 5, date: 2020-11-17T23:40:55.084Z },
{ num: 9, date: 2020-11-21T03:44:49.573Z },
{ num: 10, date: 2020-11-22T03:44:49.573Z },
{ num: 11, date: 2020-11-23T03:44:49.573Z } ]
There are several pieces of information that are not given, like how the time of the day changes, but here is a demo snippet:
const obj= {
timeline: [
{ num: 1, date: new Date("2020-11-13T16:23:57.460Z") },
{ num: 2, date: new Date("2020-11-14T20:19:42.186Z") },
{ num: 3, date: new Date("2020-11-15T14:58:09.203Z") },
{ num: 4, date: new Date("2020-11-16T18:55:38.491Z") },
// { num: 5, date: new Date("2020-11-17T23:40:55.084Z") },
// { num: 6, date: new Date("2020-11-18T03:44:49.573Z") },
// { num: 7, date: new Date("2020-11-19T03:44:49.573Z") },
{ num: 8, date: new Date("2020-11-20T03:44:49.573Z") },
{ num: 9, date: new Date("2020-11-21T03:44:49.573Z") },
{ num: 10, date: new Date("2020-11-22T03:44:49.573Z") },
{ num: 11, date: new Date("2020-11-23T03:44:49.573Z") },
]
};
function ensure_time_line(source) {
let result = {timeline: []};
let src;
let next;
for (let i = 0; i < (source.timeline.length - 1); i++) {
src = source.timeline[i];
next = source.timeline[i + 1];
let current_date = src.date;
//console.log('rc',src)
if (next) {
// console.log(next)
let tomorrow = new Date();
tomorrow.setDate(current_date.getDate() + 1);
result.timeline.push(src);
while (tomorrow.toDateString() !== next.date.toDateString()) {
src = {
num: src.num + 1,
date: new Date(tomorrow)
};
result.timeline.push(src);
tomorrow.setDate(tomorrow.getDate() + 1);
}
}
}
return result;
}
console.log(ensure_time_line(obj));
Since the time of day changes from element 4 to element 8, I have used toDateString() to compare dates.

Pushing data from this array to another uses the least loop

I want to config data from 'data2' array to 'dataConvert' array
and I want to find another way of optimizing.
let dataConvert = [];
data2 = [
{
time: "2020-7",
tasks: [
{
key: "p1",
value: 15
},
{
key: "p2",
value: 13
},
]
},
{
time: "2020-8",
tasks: [
{
key: "p1",
value: 16
},
{
key: "p2",
value: 19
},
]
},
{
time: "2020-9",
tasks: [
{
key: "p1",
value: 12
},
{
key: "p2",
value: 93
},
]
}
]
After adding data to the 'dataConvert' array, then 'dataConvert' is formatted as follows:
dataConvert = [
["x","2020-7", "2020-8", "2020-9"],
["p1", 15, 16, 12],
["p2", 13, 19, 93]
]
i tried use reduce , I want to find another way of optimizing.
let dateConvert = [], valueConvert = [];
data2.forEach(x=>{
let date = new Date(x.time);
if (date) {
let getYear = date.getFullYear();
let getMonth = date.getMonth() + 1;
let newDate = `${getYear}-${getMonth}-1`;
return dateConvert = [...dateConvert, newDate];
}
})
dateConvert.unshift("x");
// get p1 p2 value
let allTasks = data2.flatMap(x => x.tasks);
valueConvert = Object.values(allTasks.reduce((arr, item) => {
arr[item.key] = arr[item.key] || [item.key];
arr[item.key].push(item.value);
return arr;
}, {}));
dataConvert = [...[dateConvert], ...valueConvert];
thank u.
You could take nested loops and store the index in an object for faster access of key.
const
data = [{ time: "2020-7", tasks: [{ key: "p1", value: 15 }, { key: "p2", value: 13 }] }, { time: "2020-8", tasks: [{ key: "p1", value: 16 }, { key: "p2", value: 19 }] }, { time: "2020-9", tasks: [{ key: "p1", value: 12 }, { key: "p2",value: 93 }] }],
dataConvert = [['x']],
indices = {};
data.forEach(o => {
dataConvert[0].push(o.time);
o.tasks.forEach(({ key, value }) => {
if (!(key in indices)) indices[key] = dataConvert.push([key]) - 1;
dataConvert[indices[key]].push(value);
});
});
console.log(dataConvert);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Combining Like Objects by Date in JavaScript Array

I have the following array:
var objArray = [
{ num: 1, date: '1/12/2017' },
{ num: 3, date: '1/12/2017' },
{ num: 7, date: '1/12/2017' },
{ num: 1, date: '1/13/2018' },
{ num: 3, date: '1/16/2018' },
{ num: 4, date: '1/16/2018' }
];
I want to combine those with same dates so that the output array looks like this:
var outputArr = [
{ num: 11, date: '1/12/2017' },
{ num: 1, date: '1/13/2018' },
{ num: 7, date: '1/16/2018' }
];
I'm adding all num with similar dates and creating a single new object.
I have a very large dataset of objects like this so I'm trying to reduce the amount of processing time for this.
I've got the arrays sorted by date so that it mirrors objArray.
For loops seems cumbersome since I'm taking the first date in the array and checking every other element in the array a la the following pseudo-code:
var newArr = [];
for(i = 0; i < objArray.length; i++) {
for(j = 0; j < objArray.length; j++) {
var tempArr = [];
// check every date manually
// add similar to new array
tempArr.push({ similar items });
}
newArr.push(tempArr):
}
// Do another couple loops to combine those like arrays into another array
There has to be a more elegant way to perform this than running multiple for loops.
Any suggestions would be appreciated.
Simply use Array.reduce() to create a map and group values by date, Object.values() on the map will give you the desired output value:
let arr = [ { num: 1, date: '1/12/2017' }, { num: 3, date: '1/12/2017' }, { num: 7, date: '1/12/2017' }, { num: 1, date: '1/13/2018' }, { num: 3, date: '1/16/2018' }, { num: 4, date: '1/16/2018' } ];
let result = Object.values(arr.reduce((a, {num, date})=>{
if(!a[date])
a[date] = Object.assign({},{num, date});
else
a[date].num += num;
return a;
},{}));
console.log(result);
Using lodash,
// Aggregate num from unique dates
var g = _.groupBy(objArray,'date')
Object.keys(g).map(k=>({num:g[k].reduce((a,c)=>c.num+a,0),date:k}))
var objArray = [
{ num: 1, date: '1/12/2017' },
{ num: 3, date: '1/12/2017' },
{ num: 7, date: '1/12/2017' },
{ num: 1, date: '1/13/2018' },
{ num: 3, date: '1/16/2018' },
{ num: 4, date: '1/16/2018' }
];
let outputArr = Array.from(objArray.reduce((acc, obj)=>{
acc.set(obj.date, (acc.get([obj.date]) || 0) + obj.num);
return acc;
}, new Map()))
.map(kv=>({num: kv[1], date: kv[0]}))
console.log(outputArr);
gives:
[ { num: 11, date: '1/12/2017' },
{ num: 1, date: '1/13/2018' },
{ num: 7, date: '1/16/2018' } ]
You could also remove the if statements and use a Set if you wanted to be even more declarative.
var objArray = [
{ num: 1, date: '1/12/2017' },
{ num: 3, date: '1/12/2017' },
{ num: 7, date: '1/12/2017' },
{ num: 1, date: '1/13/2018' },
{ num: 3, date: '1/16/2018' },
{ num: 4, date: '1/16/2018' }
];
var mSet = new Set(objArray.map(d => d.date));
return Array.from(mSet).map(d => {
return
{
date: d,
sum: (objArray
.filter(o => o.date === d)
.map(n => n.num)
.reduce((a, c) => a + c, 0))
}
);
This returns:
[{ date: 1/12/2017, sum: 11},
{ date: 1/13/2018, sum: 1 },
{ date: 1/16/2018, sum: 7 }]
Here's another way. It's more verbose, but if you're just starting out it might be easier to understand as opposed to using array methods like reduce().
objArray = [
{ num: 1, date: '1/12/2017' },
{ num: 3, date: '1/12/2017' },
{ num: 7, date: '1/12/2017' },
{ num: 1, date: '1/13/2018' },
{ num: 3, date: '1/16/2018' },
{ num: 4, date: '1/16/2018' }
]
function combineObj(data) {
let validator= new Set();
let combinedArr = [];
let numCount = 0;
// Create a list of unique properties to match against:
data.forEach((e) => validator.add(e.date));
// For each value in the validator, create a new object in a new array
// and add the unique values from the validator to the respective property:
validator.forEach((e) => {
combinedArr.push({
num: 0,
date: e
});
})
// Lastly, for each object in the combinedArr, use a counter to sum up the total values of each property
// as you loop through your data:
combinedArr.forEach((e) => {
numCount = 0;
data.forEach((ee) => {
if (e.date === ee.date) {
numCount += ee.num;
e.num = numCount;
}
})
})
return combinedArr;
}
Returns:
[
{ num: 11, date: '1/12/2017' },
{ num: 1, date: '1/13/2018' },
{ num: 7, date: '1/16/2018' }
]

Better way to join two arrays of objects on two properties?

I'm trying to combine two arrays of objects, based on two properties, and rewrite the names of other properties in the joined dataset.
This is what the datasets look like:
var xData = [
{ row_id: 1, date: '2013-04-01', cost: 18 },
{ row_id: 2, date: '2013-04-01', cost: 27 } ...
];
var yData = [
{ row_id: 1, date: '2013-04-01', cost: 48 },
{ row_id: 3, date: '2013-04-01', cost: 37 } ...
];
The properties I want to join on are the row_id and date properties, and I want to rewrite cost to x_cost and y_cost respectively. I also want to deal with missing values. So this is what I want to end up with:
var combinedData = [
{ row_id: 1, date: '2013-04-01', x_cost: 18, y_cost: 48 },
{ row_id: 2, date: '2013-04-01', x_cost: 27, y_cost: null },
{ row_id: 3, date: '2013-04-01', x_cost: null, y_cost: 37 } ...
];
This is my code right now. It's pretty horrible:
combineXAndYDatasets: function(xData, yData) {
// Index both datasets by ID and date.
var x_indexed_by_id_and_date = {};
xData.forEach(function(d) {
var k = d.row_id + '_' + d.date;
x_indexed_by_id_and_date[k] = d;
});
var y_indexed_by_id_and_date = {};
yData.forEach(function(d) {
var k = d.row_id + '_' + d.date;
y_indexed_by_id_and_date[k] = d;
});
var combinedData = [];
// Iterate over ydata, join with xdata if possible.
for (var row_id in y_indexed_by_id_and_date) {
var row = JSON.parse(JSON.stringify(y_indexed_by_id_and_date[row_id]));
row.y_cost = +y_indexed_by_id_and_date[row_id].cost;
if (row_id in x_indexed_by_id_and_date) {
row.x_cost = +x_indexed_by_id_and_date[row_id].cost;
} else {
row.x_cost = null;
}
combinedData.push(row);
}
// Iterate over xdata, add anything that wasn't in ydata.
for (var x_row_id in x_indexed_by_id_and_date) {
if (!(x_row_id in y_indexed_by_id_and_date)) {
var x_row = JSON.parse(JSON.stringify(x_indexed_by_id_and_date[x_row_id]));
x_row.y = null;
x_row.x = +x_row.cost;
combinedData.push(x_row);
}
}
return combinedData;
}
What can I do to make this less awful?
I'm using jQuery, and I could add e.g. Underscore if that would help.
You could take advantage of reduce to reduce each array to a dictionary and then convert that dictionary back into an array. Something like this (vanilla JS, not IE 8 compatible out-of-the-box):
var xData = [
{ row_id: 1, date: '2013-04-01', cost: 18 },
{ row_id: 2, date: '2013-04-01', cost: 27 }
];
var yData = [
{ row_id: 1, date: '2013-04-01', cost: 48 },
{ row_id: 3, date: '2013-04-01', cost: 37 }
];
var xDataDict = xData.reduce(function(p,c) {
createDictionaryEntry(p,c,c.cost,null)
return p;
},{});
xAndYDataDict = yData.reduce(function(p,c) {
createDictionaryEntry(p,c,null,c.cost)
return p;
}, xDataDict);
var combinedData = Object.keys(xAndYDataDict).map(function(key) {
return xAndYDataDict[key];
});
alert(JSON.stringify(combinedData));
function createDictionaryEntry(p,c,x_cost,y_cost) {
var key = c.row_id + "-" + c.date;
if (p[key]) {
p[key].x_cost = p[key].x_cost || x_cost;
p[key].y_cost = p[key].y_cost || y_cost;
} else {
p[key] = {
row_id: c.row_id,
date: c.date,
x_cost: x_cost,
y_cost: y_cost
}
}
}
Note that combinedData won't be in any guaranteed order, so if that's important, you can always sort it afterwards.
Using underscore:
var xData = [
{ row_id: 1, date: '2013-04-01', cost: 18 },
{ row_id: 2, date: '2013-04-01', cost: 27 }
];
var yData = [
{ row_id: 1, date: '2013-04-01', cost: 48 },
{ row_id: 3, date: '2013-04-01', cost: 37 }
];
var xDataDict = _.reduce(xData, function(p,c) {
createDictionaryEntry(p,c,c.cost,null)
return p;
},{});
xAndYDataDict = _.reduce(yData,function(p,c) {
createDictionaryEntry(p,c,null,c.cost)
return p;
}, xDataDict);
var combinedData = _.map(Object.keys(xAndYDataDict),function(key) {
return xAndYDataDict[key];
});
alert(JSON.stringify(combinedData));
function createDictionaryEntry(p,c,x_cost,y_cost) {
var key = c.row_id + "-" + c.date;
if (p[key]) {
p[key].x_cost = p[key].x_cost || x_cost;
p[key].y_cost = p[key].y_cost || y_cost;
} else {
p[key] = {
row_id: c.row_id,
date: c.date,
x_cost: x_cost,
y_cost: y_cost
}
}
}
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

Categories

Resources