Combining Like Objects by Date in JavaScript Array - javascript

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' }
]

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

Remove duplicate records with same status and preserve only latest

I have below object.
const data = [
{
status: 1,
date: '2020-12-01',
},
{
status: 1,
date: '2020-11-01',
},
{
status: 2,
date: '2020-12-01',
},
{
status: 4,
date: '2020-12-01',
},
{
status: 5,
date: '2020-12-01',
}
]
I need to filter out records with status 4 and 5.
Also, need to have only latest record for status 1.
So the result would be like below.
const data = [
{
status: 1,
date: '2020-12-01',
},
{
status: 2,
date: '2020-12-01',
},
]
This is what I have tried.
data.filter(obj => [1, 2, 3].includes(obj.status))
.filter(obj => obj.status === 1)
.sort((a, b) => new Date(b.date) - new Date(a.date))
But here I am losing object with other status.
I could do by storing filtered result first and then sorting and picking up the latest record, and use something like below
const result = filteredResult.push(latestRecordWithStatusOne)
But, is it possible to achieve this using the same chaining?
After filtering for status being 1,2 or 3, you can then use Array.reduce to create an object with the latest date for each status value. Since the other status values don't have multiple entries, it's safe to use this code for all of them. You can then use Object.values to create your desired output array:
const data = [{
status: 1,
date: '2020-12-01',
},
{
status: 1,
date: '2020-11-01',
},
{
status: 2,
date: '2020-12-01',
},
{
status: 4,
date: '2020-12-01',
},
{
status: 5,
date: '2020-12-01',
}
]
const out = Object.values(data
.filter(obj => [1, 2, 3].includes(obj.status))
.reduce((c, obj) => {
c[obj.status] = c[obj.status] || obj;
if (obj.date > c[obj.status].date)
c[obj.status].date = obj.date
return c;
}, {})
);
console.log(out);
you can try:
const data = [{ status: 1, date: '2020-12-01', },
{ status: 1, date: '2020-11-01', },
{ status: 2, date: '2020-12-01', },
{ status: 4, date: '2020-12-01', },
{ status: 5, date: '2020-12-01', }
]
console.log([...new Set(Object.values(data
.filter(obj => [1, 2, 3].includes(obj.status))).map(item => item.status))])
You can do this in one go with a reduce function. Ignore the 4/5 status and check for newest status 1 and replace if needed. Otherwise, add the value.
const data = [{
status: 1,
date: '2020-12-01',
},
{
status: 1,
date: '2020-11-01',
},
{
status: 2,
date: '2020-12-01',
},
{
status: 4,
date: '2020-12-01',
},
{
status: 5,
date: '2020-12-01',
}
]
const filtered = data.reduce((accumulator, currentValue, index, array) => {
if ([4, 5].includes(currentValue.status)) {
// don't add value since it's a status 4/5
return accumulator;
} else if (currentValue.status === 1) {
// currentValue status is 1 so check if there is already one in the result
const index = accumulator.findIndex(obj => obj.status === 1)
if (index === -1) {
// no other status 1 so add it
return [...accumulator, currentValue]
} else if (accumulator[index].date < currentValue.date) {
// newer status 1 so replace it
return [...accumulator.slice(0, index), currentValue, ...accumulator.slice(index + 1)]
} else {
// already the newest so just return the current accumulator
return accumulator;
}
} else {
// any other status can just be added
return [...accumulator, currentValue];
}
}, []);
console.log(filtered)

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.

JavaScript sort array by 2 values

I've an array and I want to sort it by "id" and "date" from smaller to bigger. How can I do this correctly ?
Example :
var unsorted = [
{id: 1, date: "2015-01-18T15:00:00+01:00"},
{id: 1, date: "2015-01-18T14:30:00+01:00"},
{id: 2, date: "2015-01-18T10:00:00+01:00"},
{id: 1, date: "2015-01-18T16:00:00+01:00"},
{id: 3, date: "2015-01-18T14:15:00+01:00"},
{id: 2, date: "2015-01-18T14:00:00+01:00"}
]
Should return :
var sorted = [
{id: 1, date: "2015-01-18T14:30:00+01:00"},
{id: 1, date: "2015-01-18T15:00:00+01:00"},
{id: 1, date: "2015-01-18T16:00:00+01:00"},
{id: 2, date: "2015-01-18T10:00:00+01:00"},
{id: 2, date: "2015-01-18T14:00:00+01:00"},
{id: 3, date: "2015-01-18T14:15:00+01:00"}
]
Here is an example using array.sort:
var arr = [
{id: 1, date: "2015-01-18T15:00:00+01:00"},
{id: 1, date: "2015-01-18T14:30:00+01:00"},
{id: 2, date: "2015-01-18T10:00:00+01:00"},
{id: 1, date: "2015-01-18T16:00:00+01:00"},
{id: 3, date: "2015-01-18T14:15:00+01:00"},
{id: 2, date: "2015-01-18T14:00:00+01:00"}
];
arr.sort(function(a,b){
if (a.id == b.id) return a.date.localeCompare(b.date);
return a.id-b.id;
});
// test
for (var i in arr) {
console.log(arr[i]);
}
Result being:
Object {id: 1, date: "2015-01-18T14:30:00+01:00"}
Object {id: 1, date: "2015-01-18T15:00:00+01:00"}
Object {id: 1, date: "2015-01-18T16:00:00+01:00"}
Object {id: 2, date: "2015-01-18T10:00:00+01:00"}
Object {id: 2, date: "2015-01-18T14:00:00+01:00"}
Object {id: 3, date: "2015-01-18T14:15:00+01:00"}
You can use .sort():
var unsorted = [
{id: 1, date: "2015-01-18T15:00:00+01:00"},
{id: 1, date: "2015-01-18T14:30:00+01:00"},
{id: 2, date: "2015-01-18T10:00:00+01:00"},
{id: 1, date: "2015-01-18T16:00:00+01:00"},
{id: 3, date: "2015-01-18T14:15:00+01:00"},
{id: 2, date: "2015-01-18T14:00:00+01:00"}
];
var sorted = unsorted.sort(function(a, b) {
return a.id == b.id ?
new Date(a.date) - new Date(b.date) : a.id - b.id;
});
console.log(sorted);
Output:
[ { id: 1, date: '2015-01-18T14:30:00+01:00' },
{ id: 1, date: '2015-01-18T15:00:00+01:00' },
{ id: 1, date: '2015-01-18T16:00:00+01:00' },
{ id: 2, date: '2015-01-18T10:00:00+01:00' },
{ id: 2, date: '2015-01-18T14:00:00+01:00' },
{ id: 3, date: '2015-01-18T14:15:00+01:00' } ]
Give this a shot
var sorted = unsorted.sort(function(a, b) {
return a.id === b.id ?
Date.parse(a.date) - Date.parse(b.date) :
a.id - b.id ;
});
Explanation
If the id field is equal, we want to return the comparison of the date field.
If the id field is not equal, we will return the comparison of the id field
Array.sort takes a function with two parameters to compare two elements of an array. If this function returns a negative then a is placed before b, if it returns positive then a is placed before b and if it returns 0 they stay as they are. Here I compare them by id and if their IDs are same then I compare them by date.
var unsorted = [{
id: 1,
date: "2015-01-18T15:00:00+01:00"
}, {
id: 1,
date: "2015-01-18T14:30:00+01:00"
}, {
id: 2,
date: "2015-01-18T10:00:00+01:00"
}, {
id: 1,
date: "2015-01-18T16:00:00+01:00"
}, {
id: 3,
date: "2015-01-18T14:15:00+01:00"
}, {
id: 2,
date: "2015-01-18T14:00:00+01:00"
}];
unsorted.sort(function(a, b) {
if (a.id < b.id)
return -1;
else if (a.id > b.id)
return 1;
else {
if (a.date < b.date)
return -1;
else if (a.date > b.date)
return 1;
else
return 0;
}
});
Divide and conquer!
Start by reducing the input array into a map of id => object, ie:
var dataById = unsorted.reduce(function (soFar, value) {
// Initialise the array if we haven't processed this
// id yet.
if (soFar[value.id] === undefined) {
soFar[value.id] = [];
}
// ad this object to Array.
soFar[value.id].push(value);
return soFar;
}, {});
Now you can sort each array by looping over the Object's keys, note this modifies the dataById map in place.
Object.keys(dataById).forEach(function (id) {
dataById[id] = dataById[id].sort();
});
Finally, you can combine all the data together, again by iterating over the keys in the map. Note that maps (objects) in javascript don't guarantee the order of their keys, so you may wish to dump the ids out to an Array first before iterating:
var ids = Object.keys(dataById).sort();
// Reduce the ids into an Array of data.
var ids.reduce(function (soFar, value) {
return soFar.concat(dataById[id]);
}, []);
Not the most efficient way of solving your problem, but hopefully it gives you some help with the thought process.

Converting Array of Objects into Array of Arrays

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;
}

Categories

Resources