可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
What is the best way to group objects by date and add them all up to create a single JavaScript object? I prefer code readability and lesser lines of code over performance as the application is not data intensive. Moreover there are going to be lots people who are going to make changes after I'm done with my internship.
Here is some sample data
[
{"Timestamp":"Thu, 01 Jan 2015 00:57:00 GMT","cp":2,"pc":2},
{"Timestamp":"Thu, 01 Jan 2015 01:57:00 GMT","cp":0,"pc":4},
{"Timestamp":"Thu, 01 Jan 2015 02:57:00 GMT","cp":2,"pc":2},
{"Timestamp":"Thu, 01 Jan 2015 03:57:00 GMT","cp":0,"pc":4},
{"Timestamp":"Thu, 02 Jan 2015 00:57:00 GMT","cp":2,"pc":2},
{"Timestamp":"Thu, 02 Jan 2015 01:57:00 GMT","cp":0,"pc":4},
{"Timestamp":"Thu, 02 Jan 2015 02:57:00 GMT","cp":2,"pc":2},
{"Timestamp":"Thu, 02 Jan 2015 03:57:00 GMT","cp":0,"pc":4}
]
I want to create this out of the above data.
[ {"Date":"2015-01-01", "cp":4, "pc":12}, {"Date":"2015-01-02", "cp":4, "pc"12} ]
If you notice, the resultant JavaScript object is the sum total of all the columns on that particular date and replace timestamp by date.
We already use moment.js in the application, so I have it at disposal. If you think moment can solve the problem in a neater fashion, please let me know.
回答1:
- Iterate your array of objects (
$.each()
function can be used to iterate over any collection.)
- Convert
UTC
format date string to ISO
format using toISOString()
method.
- Maintain common array for date so that you can easily map your repeated date location using
indexOf()
method.
Here is the Code:
var arr = [
{"Timestamp":"Thu, 01 Jan 2015 00:57:00 GMT","cp":2,"pc":2},
{"Timestamp":"Thu, 01 Jan 2015 01:57:00 GMT","cp":0,"pc":4},
{"Timestamp":"Thu, 01 Jan 2015 02:57:00 GMT","cp":2,"pc":2},
{"Timestamp":"Thu, 01 Jan 2015 03:57:00 GMT","cp":0,"pc":4},
{"Timestamp":"Thu, 02 Jan 2015 00:57:00 GMT","cp":2,"pc":2},
{"Timestamp":"Thu, 02 Jan 2015 01:57:00 GMT","cp":0,"pc":4},
{"Timestamp":"Thu, 02 Jan 2015 02:57:00 GMT","cp":2,"pc":2},
{"Timestamp":"Thu, 02 Jan 2015 03:57:00 GMT","cp":0,"pc":4}
];
var resultArr = [];
var dateArr = [];
$.each(arr, function () {
// Easiest way to get your required date format
var date = new Date(this.Timestamp).toISOString().replace(/T/, ' ').split(' ')[0];
var index = dateArr.indexOf(date);
if (index == -1) {
dateArr.push(date);
var obj = {Date: date, cp: this.cp, pc: this.pc};
resultArr.push(obj);
}
else {
resultArr[index].cp += this.cp;
resultArr[index].pc += this.pc;
}
});
console.log(resultArr); // [ {"Date":"2015-01-01", "cp":4, "pc":12}, {"Date":"2015-01-02", "cp":4, "pc"12} ]
Hope this may helpful for you.
回答2:
Try this.
var timeArray=[
{"Timestamp":"Thu, 01 Jan 2015 00:57:00 GMT","cp":2,"pc":2},
{"Timestamp":"Thu, 01 Jan 2015 01:57:00 GMT","cp":0,"pc":4},
{"Timestamp":"Thu, 01 Jan 2015 02:57:00 GMT","cp":2,"pc":2},
{"Timestamp":"Thu, 01 Jan 2015 03:57:00 GMT","cp":0,"pc":4},
{"Timestamp":"Thu, 02 Jan 2015 00:57:00 GMT","cp":2,"pc":2},
{"Timestamp":"Thu, 02 Jan 2015 01:57:00 GMT","cp":0,"pc":4},
{"Timestamp":"Thu, 02 Jan 2015 02:57:00 GMT","cp":2,"pc":2},
{"Timestamp":"Thu, 02 Jan 2015 03:57:00 GMT","cp":0,"pc":4}
]
var object = {}, resultArray = [];
for (var i = 0; i < timeArray.length; i++) {
var date = timeArray[i].Timestamp;
var localDateString = new Date(date).getFullYear() + '-' + (new Date(date).getMonth() + 1) + '-' + new Date(date).getDate();
if (object[localDateString]) {
object[localDateString].cp += timeArray[i].cp;
object[localDateString].pc += timeArray[i].pc;
} else {
timeArray[i].Date = localDateString;
delete timeArray[i].Timestamp;
object[localDateString] = timeArray[i];
}
}
for (var prop in object)
resultArray.push(object[prop]);
console.log(resultArray);
回答3:
I believe a simple utility library such as Underscore.js or Lodash could do the job, however, this looks like a task plain old vanilla Javascript can take on by itself.
Check out the Array.prototype.map function, or probably better yet an Array.prototype.sort that takes in a sorting function applying logic to a given object's .Timestamp
property.
Edit: something like
yourArray.sort(function(objA, objB){
return objA.Timestamp > objB.TimeStamp ? -1 : 1;
});
may work.
EDIT: I see now you are trying to merge dates. In that case, I would say Array.prototype.map
chained with Array.prototype.reduce
is a possible path to go down. You could also (messily) use Array.prototype.filter
to push all arrays of a given date into a single array, and so on for each date.
Edit:
How about a reduce, then?
var thingYouWant = yourArray.reduce(function(summed, current){
date = changeIntoOnlyDayDate(current.Timestamp);
var found = false;
summed.forEach(function(obj){
if(obj.Timestamp === date){ obj.cp++; found = true;};
}
if(!found){summed.push(turnThisDateIntoDesiredObject(date))}
}
return summed;
}, []);