Related
This is what I've tried and it seems like I'm on the right path but I've been trying to tweak this algorithm for a while and I can't figure out what I'm doing wrong. Here is my code so far:
const getThem = async () => {
const format2 = 'YYYY/MM/DD';
const obj = {};
for (let i = 0; i < data.length; i++) {
for (let j = 0; j < data[i].tests.length; j++) {
for (let z = 0; z < channel.length; z++) {
if (data[i].tests[j] === channel[z].id) {
const dateTime = moment(channel[z].start).format(format2);
const dateTime2 = moment(channel[z].end).format(format2);
const dateList = getDateArray(new Date(dateTime), new Date(dateTime2));
if (Date.parse(dateTime) > Date.parse('2019-11-15') || Date.parse(dateTime) < Date.parse('2019-11-04')) {
break;
}
if (!channel[z].end) {
// eslint-disable-next-line operator-assignment
obj[dateTime] += (1 / data.length);
} else {
for (let k = 0; k < dateList.length; k++) {
if (!obj.hasOwnProperty(dateList[k])) {
obj[dateList[k]] = 1 / data.length;
} else {
obj[dateList[k]] += (1 / data.length);
}
}
}
}
}
}
}
setDates(Array.sort(Object.keys(obj)));
setValues(Object.values(obj));
};
Check my answer. The approach is simple. First we loop through all the testsResponse data and get the minimum and maximum dates then we iterate through each day from min to max date. For each current day we check the test ids in testsResponse data and then we filter the channels data from the tests array in channelsResponse data and then finally we take the % by the filtered channels data and total channels response data and push it in the results array. The only catch here is that it will push all the dates between minimum test.start and maximum test.end dates both inclusive. If you want to exclude the dates for which testIds is empty then just before the results.push() check if testIds.length is not 0. Here is the getThem():
// given channelsResponse & testsResponse
const getThem = () => {
// get min and max dates
let max='';
let min=new Date().toISOString();
testsResponse.forEach(test => {
min=test.start && min.localeCompare(test.start)>0?test.start:min;
max=test.end && max.localeCompare(test.end)<0?test.end:max;
});
min=new Date(min.substr(0,10)+'T00:00:00.000Z');
max=new Date(max.substr(0,10)+'T00:00:00.000Z');
let results = [];
// loop from min date to max date
for(var i=min; i<=max; i.setDate(i.getDate()+1)) {
let p=0;
let d=i.toISOString().substr(0,10);
// get test ids within the current date
const testIds = testsResponse.filter(t => d.localeCompare((t.start+'').substr(0,10))>=0 && d.localeCompare((t.end+'').substr(0,10))<=0).map(t => t.id);
// get channels where above test ids were found
const channels = channelsResponse.filter(c => c.tests.some(t => testIds.includes(t)));
// calculate %
p=Math.round(channels.length*100.0/channelsResponse.length);
// push data for current date to results
results.push({date: i.toISOString(), utilizationPercentage: p})
}
return results;
};
console.log(getThem());
// [{"date":"2019-11-04T00:00:00.000Z","utilizationPercentage":14},{"date":"2019-11-05T00:00:00.000Z","utilizationPercentage":86},{"date":"2019-11-06T00:00:00.000Z","utilizationPercentage":71},{"date":"2019-11-07T00:00:00.000Z","utilizationPercentage":43},{"date":"2019-11-08T00:00:00.000Z","utilizationPercentage":57},{"date":"2019-11-09T00:00:00.000Z","utilizationPercentage":29},{"date":"2019-11-10T00:00:00.000Z","utilizationPercentage":29},{"date":"2019-11-11T00:00:00.000Z","utilizationPercentage":57},{"date":"2019-11-12T00:00:00.000Z","utilizationPercentage":57},{"date":"2019-11-13T00:00:00.000Z","utilizationPercentage":57},{"date":"2019-11-14T00:00:00.000Z","utilizationPercentage":43},{"date":"2019-11-15T00:00:00.000Z","utilizationPercentage":43}]
Check the demo code here: https://ideone.com/L2rbVe
To avoid iteration over your inputs several times, getting a bad time complexity, I would suggest using Maps and Sets, so you can find related information efficiently.
I kept your function getDateArray. As you didn't provide its source, I reproduced it. But you may want to use your own:
const channelsResponse = [{id: 372,name: 'Channel 01',lab: 'Fullerton',tests: [3, 4, 7, 8],},{id: 373,name: 'Channel 02',lab: 'Fullerton',tests: [1, 2, 5, 6],},{id: 374,name: 'Beta Channel',lab: 'Fullerton',tests: [],},{id: 472,name: 'Channel 01',lab: 'Queens',tests: [9, 11, 12, 13],},{id: 473,name: 'Channel 02',lab: 'Queens',tests: [15, 17, 19],},{id: 474,name: 'Channel 03',lab: 'Queens',tests: [21, 22, 24, 25],},{id: 475,name: 'Channel 04',lab: 'Queens',tests: [26, 27, 28, 29, 30],},];
const testsResponse = [{id: 1,start: '2019-11-05T11:05:00Z',end: '2019-11-05T13:05:00Z',},{id: 2,start: '2019-11-06T11:05:00Z',end: '2019-11-06T13:05:00Z',},{id: 3,start: '2019-11-04T11:05:00Z',end: '2019-11-04T13:09:00Z',},{id: 4,start: '2019-11-04T17:00:00Z',end: '2019-11-05T09:32:00Z',},{id: 5,start: '2019-11-11T11:05:00Z',end: '2019-11-12T13:05:00Z',},{id: 6,start: '2019-11-12T14:05:00Z',end: '2019-11-15T13:05:00Z',},{id: 7,start: '2019-11-07T11:05:00Z',end: '2019-11-08T13:05:00Z',},{id: 8,start: '2019-11-08T15:05:00Z',end: '2019-11-08T15:35:00Z',},{id: 9,start: '2019-11-05T09:05:00Z',end: '2019-11-08T12:05:00Z',},{id: 11,start: '2019-11-08T12:35:00Z',end: '2019-11-08T13:35:00Z',},{id: 12,start: '2019-11-08T17:00:00Z',end: '2019-11-11T10:00:00Z',},{id: 13,start: '2019-11-11T12:00:00Z',end: null,},{id: 15},{id: 17,start: '2019-11-05T17:00:00Z',end: '2019-11-06T10:00:00Z',},{id: 19,start: '2019-11-06T12:00:00Z',end: '2019-11-06T13:22:00Z',},{id: 21,start: '2019-11-05T09:05:00Z',end: '2019-11-06T12:05:00Z',},{id: 22,start: '2019-11-08T12:35:00Z',end: '2019-11-08T13:35:00Z',},{id: 24,start: '2019-11-11T17:00:00Z',end: '2019-11-15T10:00:00Z',},{id: 25,start: '2019-11-15T12:00:00Z',},{id: 26,start: '2019-11-05T09:05:00Z',end: '2019-11-06T12:05:00Z',},{id: 27,start: '2019-11-07T12:35:00Z',end: '2019-11-07T13:35:00Z',},{id: 28,start: '2019-11-08T17:00:00Z',end: '2019-11-11T10:00:00Z',},{id: 29,start: '2019-11-12T12:00:00Z',end: '2019-11-12T14:00:00Z',},{id: 30,start: '2019-11-13T12:00:00Z',end: '2019-11-13T14:00:00Z',},];
function getDateArray(start, end) {
if (!start || !end) return [];
let date = new Date(start.slice(0,11) + "00:00:00Z");
let last = Date.parse(end.slice(0,11) + "00:00:00Z");
let dates = [date.toJSON()];
while (+date != last) {
date.setDate(date.getDate()+1);
dates.push(date.toJSON());
}
return dates; // array of date-strings
}
// Create two maps for faster retrieval
let mapTestToDates = new Map(testsResponse.map(( { id, start, end }) => [id, getDateArray(start, end)]));
let allDates = [...new Set([...mapTestToDates.values()].flat())].sort();
let mapDateToChannels = new Map(allDates.map(date => [date, new Set]));
// Main data collection loop
for (let channel of channelsResponse) {
for (let test of channel.tests) {
for (let date of mapTestToDates.get(test)) {
mapDateToChannels.get(date).add(channel);
}
}
}
// Finally calculate the percentages
let result = Array.from(mapDateToChannels.entries(), ([date, channels]) =>
({ date, utilizationPercentage: Math.round(channels.size * 100 / channelsResponse.length) })
);
console.log(result);
const arr = [
{"datetime":"2018/8/5","value":85,"type":"A"},
{"datetime":"2018/8/10","value":7,"type":"B"},
{"datetime":"2018/8/10","value":73,"type":"A"}
];
I have an array as you can see in the snippet. My issue is I need to check something per day:
For each day when A value > 60 or when B value > 6 then do something.
Else when A value <= 60 and when B value <= 6 then do something else.
And I don't know how to do this check with the current array structure as each step in the loop is a different day. I want to compare all values for one day at the same time.
Is it possible to transform the array to look like this? Then I will be able to compare day per day...
const arr = [
{"datetime":"2018/8/5","valueA":85,"valueB":undefined},
{"datetime":"2018/8/10","valueB":7,"valueA":73}
];
Thank you!
You can make a the date groups by reducing into an object. Then just set the appropriate value in that object. In the end your array will be in the Object.keys() of the grouped object.
[As you might surmise from the comments, the order of the final array is not guaranteed because object keys and values are not guaranteed. If your original data is ordered by date, you should say so in the question because there will be more efficient ways to do this if the order is guaranteed].
const arr = [{"datetime":"2018/8/5","value":85,"type":"A"},{"datetime":"2018/8/10","value":7,"type":"B"},{"datetime":"2018/8/10","value":73,"type":"A"}];
let groups = arr.reduce((obj, {datetime, value, type}) => {
if (!obj[datetime]) obj[datetime] = {datetime, valueA:undefined, valueB:undefined}
let currentKey = type == 'A' ? "valueA" : "valueB"
obj[datetime][currentKey] = value
return obj
},{})
let newArr = Object.values(groups)
console.log(newArr)
This will transform the array as OP asked for, and will respect the order.
const arr = [{"datetime":"2018/8/5","value":85,"type":"A"},
{"datetime":"2018/8/10","value":7,"type":"B"},
{"datetime":"2018/8/10","value":73,"type":"A"}];
var daysArr = []
arr.map(function(day){
var keyName = 'value'+day.type
var found = false
var dayObj = {}
for (var i=0; i < daysArr.length; i++) {
if (daysArr[i].datetime === day.datetime) {
daysArr[i][keyName] = day.value;
found = true
break
}
}
if (!found) {
dayObj = {"datetime":day.datetime,valueA:undefined,valueB:undefined}
dayObj[keyName] = day.value
daysArr.push(dayObj)
}
})
console.log(daysArr);
One solution could be using reduce(). Note that if a key is not defined will return undefined (this is exemplified on the second log to the console), so I consider redundant to define, for example "value-B": undefined, unless you want to assign to it another default value.
Warning: As discussed on the comments, you should note that the order of the final result, may not be preserved.
const arr = [
{"datetime":"2018/8/5","value":85,"type":"A"},
{"datetime":"2018/8/10","value":7,"type":"B"},
{"datetime":"2018/8/10","value":73,"type":"A"}
];
let res = arr.reduce((acc, {datetime, value, type: type}) =>
{
acc[datetime] = acc[datetime] || {};
Object.assign(acc[datetime], {datetime, [`value-${type}`]: value});
return acc;
}, {});
console.log(Object.values(res));
console.log(Object.values(res)[0]["value-B"]);
You could do this:
<html>
<head>
<meta charset="UTF-8"></meta>
<script type="text/javascript">
const arr = [{"datetime":"2018/8/5","value":85,"type":"A"},
{"datetime":"2018/8/10","value":7,"type":"B"},
{"datetime":"2018/8/10","value":73,"type":"A"}];
var new_arr = group_items(arr)
console.log(new_arr)
function group_items(arr)
{
var ret_arr = []
for(var x=0;x<arr.length;x++)
{
var cur_date = arr[x].datetime
var pos = lookup_date(cur_date, ret_arr)
var obj = {}
obj.datetime = cur_date
if(pos != false)
{
//add to existing item
if(arr[x].type == 'A')
{
ret_arr[pos].valueA = arr[x].value
}
else if(arr[x].type == 'B')
{
ret_arr[pos].valueB = arr[x].value
}
}
else{
if(arr[x].type == 'A')
{
obj.valueA = arr[x].value
}
else if(arr[x].type == 'B')
{
obj.valueB = arr[x].value
}
ret_arr.push(obj)
}
}
return ret_arr
}
function lookup_date(date, arr)
{
/*
returns the position in arr of date
*/
var retval = false
for(var x=0;x<arr.length;x++)
{
if(arr[x].datetime == date)
{
retval = x
break
}
}
return retval
}
</script>
</head>
<body>
</body>
If you don't need the final array to include the datetimes in the same order as the original, then you can just make an object that maps datetimes to the corresponding values and then use Object.values to get the final array. This approach does not guarantee order, since objects are unordered data structures:
const arr = [
{"datetime":"2018/8/5","value":85,"type":"A"},
{"datetime":"2018/8/10","value":7,"type":"B"},
{"datetime":"2018/8/10","value":73,"type":"A"}
];
const values_by_date = { };
arr.forEach( ({ datetime, type, value }) =>
values_by_date[ datetime ] = {
datetime/*, valueA: undefined, valueB: undefined*/,
...values_by_date[ datetime ], [`value${type}`]: value
}
);
const result = Object.values( values_by_date );
console.log( result );
If you need the final array to include the datetimes in the same order as the original array and the original array is already sorted by datetime, you can do it in a single pass like this:
const arr = [
{"datetime":"2018/8/5","value":85,"type":"A"},
{"datetime":"2018/8/10","value":7,"type":"B"},
{"datetime":"2018/8/10","value":73,"type":"A"}
];
const result = arr.reduce( ({ result, datetime: prev }, { datetime, type, value }) => {
if ( datetime !== prev )
result.push( { datetime/*, valueA: undefined, valueB: undefined*/ } );
Object.assign( result[ result.length - 1 ], { [`value${type}`]: value } );
return { result, datetime };
}, { result: [] } ).result;
console.log( result );
Note: In either snippet you can uncomment /*, valueA: undefined, valueB: undefined*/ if you want the resulting objects to include properties for the missing values.
Hi friends I'm beginner for javascript how i sum same n no's of object name corresponding value and push the result to new array.see this is sample object
var obj_1 ={'delivered':10,'due':11,'team_name':'UK'};
var obj_2 ={'delivered':10,'due':11,'team_name':'US'};
var obj_nth ={'delivered':10,'due':11,'team_name':'UK'};
but i expect this output [UK:{'delivered':20,'due':22},US:{'delivered':10,'due':11}],so please help me what i'll do next
You can first create array of objects and then reduce() to return one object.
var obj_1 ={'delivered':10,'due':11,'team_name':'UK'};
var obj_2 ={'delivered':10,'due':11,'team_name':'US'};
var obj_nth ={'delivered':10,'due':11,'team_name':'UK'};
var result = [obj_1, obj_2, obj_nth].reduce(function(r, e) {
if(!r[e.team_name]) {
r[e.team_name] = {delivered:0,due:0}
}
r[e.team_name].delivered += e.delivered
r[e.team_name].due += e.due
return r
}, {})
console.log(result)
const newArray = initialArray.map(({team_name, ...restProps}) => {
return {
[team_name]: {...restProps}
};
});
See:
Arrow functions
Spread operator
Array.prototype.map
Computed property names
var obj_1 ={'delivered':10,'due':11,'team_name':'UK'};
var obj_2 ={'delivered':10,'due':11,'team_name':'US'};
var obj_nth ={'delivered':10,'due':11,'team_name':'UK'};
function sum_all() {
var sum={};
for(var i=0;i<arguments.length;i++) {
obj = arguments[i];
if (!sum[obj.team_name]) {
sum[obj.team_name]={'delivered':0,'due':0};
}
sum[obj.team_name].delivered += obj.delivered;
sum[obj.team_name].due += obj.due;
}
return sum;
}
var sum = sum_all(obj_1,obj_2,obj_nth);
console.log(sum);
Your console output will be:
sum
Object
UK: Object
delivered: 20
due: 22
US: Object
delivered: 10
due: 11
Store these objects in an array, such as:
var myObjects = [
{'delivered':10,'due':11,'team_name':'UK'},
{'delivered':10,'due':11,'team_name':'US'},
{'delivered':10,'due':11,'team_name':'UK'}
];
Create a new object in which you will store your results:
var results = {};
Then iterate through the array with a for loop (as it is generally faster) and add the other properties according to team_name:
for (var i = 0; i <= myObjects.length; i++) {
if (typeof results[myObjects[i].team_name] !== undefined) {
results[myObjects[i]].delivered += myObjects[i].delivered;
results[myObjects[i]].due += myObjects[i].due;
} else {
// Set 0 to these properties if the entry didn't exist
results[myObjects[i]].delivered = 0;
results[myObjects[i]].due = 0;
}
}
I have an array which looks like:
var data = [{"year":[1981],"weight":[3]},
{"year":[1982],"weight":[4]},
{"year":[1985],"weight":[7]}]
My data series starts with year 1980 and ends with year 1986. My task is to input all missing values into the array; in my case the final array should be:
var data = [{"year":[1980],"weight":[0]},
{"year":[1981],"weight":[3]},
{"year":[1982],"weight":[4]},
{"year":[1983],"weight":[0]},
{"year":[1984],"weight":[0]},
{"year":[1985],"weight":[7]},
{"year":[1986],"weight":[0]}]
I implemented this task in two steps. First I created an empty array with length of seven elements (for years 1980 - 1986) and initialize each element with value {"year": $CURRENT_YEAR, "weight": 0}. Then I loop through data array, find index of current year in the empty array and replace year and weight fields with current values. My code is pasted below.
I wonder if the code could be rewritten in a more elegant way.
// Create empty array
var my_array = []
var length = 7
// 1st step
year = 1980
for (var i = 0; i < length; i++) {
my_array.push({"year": year, "weight": 0});
year++
}
// 2nd step
for (var j = 0; j < data.length; j++) {
curr_year = data[j]["year"][0];
curr_weight = data[j]["weight"][0]
var index = my_array.findIndex(function(item, i) {return item.year === curr_year})
my_array[index] = {"year": curr_year, "weight": curr_weight}
}
It's best to do this job by .map() Besides if you have a large input array it might be wise to set up a hash (lut) in the first place such as;
var data = [{"year":[1981],"weight":[3]},
{"year":[1982],"weight":[4]},
{"year":[1985],"weight":[7]}],
lut = data.reduce((p,c) => p[c.year[0]] ? p : (p[c.year[0]] = c, p), {});
range = [1980,1986],
result = Array(range[1]-range[0] + 1).fill()
.map((_,i) => lut[i+range[0]] ? lut[i+range[0]] : {year: [i+range[0]], weight: [0]});
console.log(result);
You can combine the 2 loops and do both steps in one loop
// Create empty array
var my_array = []
var length = 7
year = 1980
for (var i = 0; i < length; i++) {
// check if there is data for the year
var index = data.findIndex(function(item, i) {return item.year === year});
if(index > -1){ //if there is data, use it
my_array.push({"year": data[index]["year"][0], "weight": data[index]["weight"][0]});
}else{ //put in default data
my_array.push({"year": year, "weight": 0});
}
year++;
}
Find index of element in array each time is bad performance for large data. I can suggest the following algorithm:
// Create empty object and fill it with values where keys are years
var years = {};
data.forEach(item => {
years[item.year[0]] = item.weight[0];
});
// Result array with all years
var result = [];
var startYear = 1980;
var endYear = 1986;
// Generate our result array
for (var i = startYear; i <= endYear; i++) {
// If property for given year (i) exists in "years" object then add it to "result" array
// in other case add default object with weight 0
var o = years[i] ? { year: [i], weight: [years[i]] } : { year: [i], weight: [0] };
result.push(o);
}
You could do this with just find() and while loop.
var data = [{"year":[1981],"weight":[3]},{"year":[1982],"weight":[4]},{"year":[1985],"weight":[7]}];
var i = 1980;
var result = [];
while(i <= 1986) {
var find = data.find(e => e.year[0] == i);
(find) ? result.push(find) : result.push({year: [i], weight: [0]});
i++;
}
console.log(result)
You could also first use map() to get array of years and then use while loop with indexOf().
var data = [{"year":[1981],"weight":[3]},{"year":[1982],"weight":[4]},{"year":[1985],"weight":[7]}];
var i = 1980;
var result = [];
var years = data.map(e => e.year[0]);
while(i <= 1986) {
var ind = years.indexOf(i);
(ind != -1) ? result.push(data[ind]) : result.push({year: [i], weight: [0]});
i++;
}
console.log(result)
I have an array with the following values (example):
[
1367848800000: true,
1367935200000: true,
1368021600000: true,
1368108000000: true,
1368194400000: true,
1368367200000: true,
1368540000000: true,
1368626400000: true,
1368712800000: true
]
Where the index is a date time. The date time will always be at 12:00:00 on a date.
In this example, the first five dates are consecutive, then one day by itself, and then another group of 3 dates. An example of what I mean is below.
Now, what I am trying to do is find sequential dates and put them into an array as follows:
[
1367848800000,
1367935200000,
1368021600000,
1368108000000,
1368194400000
],
[
1368367200000,
1368540000000,
1368626400000,
],
[
1368712800000Ω
]
So in the end, I have an array, with 3 arrays of all the times.
I have tried numerous pieces of code, but everything bugs out and nothing is worth posting on here. Any help would be much appreciated!
The following approach uses array .reduce() method:
var arr = [1367848800000, 1367935200000, 1368021600000,
1368108000000, 1368194400000, 1368367200000,
1368540000000, 1368626400000, 1368712800000],
i = 0,
result = arr.reduce(function(stack, b) {
var cur = stack[i],
a = cur ? cur[cur.length-1] : 0;
if (b - a > 86400000) {
i++;
}
if (!stack[i])
stack[i] = [];
stack[i].push(b);
return stack;
}, []);
console.log(result);
DEMO: http://jsfiddle.net/gbC8B/1/
Sth like this could do:
function sequentialize(dArr) {
dArr = Object.keys(dArr).slice().sort();
var last;
var arrs = [[]];
for (var i = 0, l = dArr.length; i < l; i++) {
var cur = new Date();
cur.setTime(dArr[i]);
last = last || cur;
if (isNewSequence(cur, last)) {
arrs.push([]);
}
arrs[arrs.length - 1].push(cur.getTime()); //always push to the last index
last = cur;
}
return arrs;
function isNewSequence(a, b) {
if (a.getTime() - b.getTime() > (24 * 60 * 60 * 1000))
return true;
return false;
}
}
Now if you pass your example Array/Object to the sequentialize function
var dates = {
1367848800000: true,
1367935200000: true,
1368021600000: true,
1368108000000: true,
1368194400000: true,
1368367200000: true,
1368540000000: true,
1368626400000: true,
1368712800000: true
};
console.log(sequentialize(dates));
This gives the following output
[
[
1367848800000,
1367935200000,
1368021600000,
1368108000000,
1368194400000
],
[
1368367200000
],
[
1368540000000,
1368626400000,
1368712800000
]
]
This simply
creates an array out of the Date keys,
Sorts them
Iterates over them
If the difference of the Current and Last Date is greate than a day
Push a new Array to the Sequence Array
Push the Current Date to the last Array in the Sequence Array
Demo on JSBin
Note: You may have to change the isNewSequence function to actually fit your needs
Gotta love these puzzles. Nice answers everyone, here's mine more jQueryish approach.
var datearray = {
1367848800000: true,
1367935200000: true,
1368021600000: true,
1368108000000: true,
1368194400000: true,
1368367200000: true,
1368540000000: true,
1368626400000: true,
1368712800000: true
};
$(function() {
var result = dateSequences(datearray);
}
function dateSequences(array) {
// parse json object to array of keys
var keys = Object.keys(array);
// sort it up
keys = keys.sort();
// convert them to dates
var dates = new Array();
$.each(keys, function(i) {
dates.push(new Date(parseInt(keys[i])));
});
// now we have array of dates, search for sequential dates
var final = new Array();
var prevdate = undefined;
var currentseq = 0;
$.each(dates, function(i, d) {
// undefined?
// first sequence
if (prevdate == undefined) {
final.push(new Array());
final[currentseq].push(d);
}
else {
// compare if difference to current date in loop is greater than a day
var comp=new Date();
comp.setDate(prevdate.getDate()+2);
// Advance sequence if it is
if (comp < d) {
currentseq++;
final[currentseq] = new Array();
}
// Push the date to current sequence
final[currentseq].push(d);
}
// store previous
prevdate = d;
});
return final;
}
Fiddle:
http://jsfiddle.net/f57Ah/1/
tried array sort with forEach
var dates = [1367848800000, 1367935200000, 1368021600000,
1368108000000, 1368194400000, 1368367200000,
1368540000000, 1368626400000, 1368712800000];
var k = 0 , sorted = [[]];
dates.sort( function ( a, b ){
return +a > +b ? 1 : +a == +b ? 0: -1;
})
.forEach( function( v , i ){
var a = v,b = dates[i+1]||0;
sorted[k].push( +a );
if ( (+b - +a) > 86400000) {
sorted[++k] = []
}
});
Later you can sort them per counts
sorted.sort( function ( a,b ){
return a.length > b.length ? -1: 1;
});
The sorted array contains desired result jsfiddle
// Preconditions: singleArray contains the input array with each element corresponding to a time index. singleArray is sorted.
var outputArray = new Array();
var stack = new Array();
var stackSize = 0;
var i;
for( i = 0; i < singleArray.length; i++ )
{
// Get the last element on the stack
var lastElement = (stackSize == 0) ? 0 : stack.pop();
// Compare to see if difference is one day
if( singleArray[i] - lastElement == 86400000 ) // 24 * 60 * 60 * 1000
{
// Dates are 1 day apart
if( lastElement != 0 ) stack.push(lastElement);
stack.push(singleArray[i]);
stackSize++;
}
else
{
if( lastElement != 0 ) stack.push(lastElement);
var tempQueue = new Array();
while(stackSize > 0)
{
// Build up a new array containing consecutive days
// using a queue
tempQueue.push(stack.pop());
stackSize--;
}
// Push the consecutive days onto the next place in the output array.
outputArray.push(tempQueue);
// Start a new group of consecutive dates
stack.push(singleArray[i]);
stackSize++;
}
}