I have a json given below
0 : {car_rental_id: "6007", sharing_schedule: "9:00 AM", booked_cars: '1', woo_order_id: "6421", woo_status: "on-hold" }
1 : {car_rental_id: "6007", sharing_schedule: "9:00 AM", booked_cars: '3', woo_order_id: "6424", woo_status: "pending" }
2 : {car_rental_id: "6007", sharing_schedule: "10:00 AM", booked_cars: '5', woo_order_id: "6427", woo_status: "pending"}
The goal here is to get the total number of booked_cars on a time. So according to this json. I should get
4 bookings for 9:00 AM and 5 bookings for 10:00 AM.
How do I achieve that?
var test = [{
car_rental_id: "6007",
sharing_schedule: "9:00 AM",
woo_order_id: "6421",
woo_status: "on-hold",
booked_cars: '1'
}, {
car_rental_id: "6007",
sharing_schedule: "9:00 AM",
woo_order_id: "6424",
woo_status: "pending",
booked_cars: '3'
}, {
car_rental_id: "6007",
sharing_schedule: "10:00 AM",
woo_order_id: "6427",
woo_status: "pending",
booked_cars: '5'
}];
var carsBookedByTime = test.reduce(function(collection, element){
var bookedCars = parseInt(element.booked_cars);
//initialize total in the collection if it does not exist
if (!collection[element.sharing_schedule]) collection[element.sharing_schedule] = 0;
collection[element.sharing_schedule] += bookedCars;
return collection;
}, {});
console.log(carsBookedByTime);
You could change it to something like that.
var values = window.confirmedBookings.reduce(function(prev, current) {
if(!prev[current.sharing_schedule]) prev[current.sharing_schedule] = 0;
prev[current.sharing_schedule] += Number(current.booked_cars);
return prev;
}, {})
#edit: updated an answer to fit a question.
You appear to be asking for :
window.totalBooked = {};
$.each(window.confirmedBookings, function(index, value) {
console.log(value.booked_cars);
window.totalBooked[value.sharing_schedule] = (window.totalBooked[value.sharing_schedule] || 0) + +value.booked_cars;
});
or, slightly simpler :
window.totalBooked = window.confirmedBookings.reduce(function(obj, value) {
obj[value.sharing_schedule] = (obj[value.sharing_schedule] || 0) + +value.booked_cars;
return obj;
}, {});
DEMO
Related
I am trying to find the common data from multiple arrays of object that contains a unique id (mongoose object id) and an array of string.
for example:
array1 = [{
_id: "60f027f98b55eb2df1f36c04",
date: "2021-07-15T12:18:12.223Z",
time: "30",
hours: ["8:00 AM", "8:30 AM"]
}]
array2 = [{
_id: "60f027f98b55eb2df1f36c05",
date: "2021-07-15T12:18:12.223Z",
time: "60",
hours: ["7:30 AM", "8:30 AM", "9:30AM"]
}]
array3 = [{
_id: "60f027f98b55eb2df1f36c06",
date: "2021-07-16T12:12:12.223Z",
time: "30",
hours: ["7:00 AM", "8:30 AM"]
}]
The output should have maximum common values in the arrays for maximum common dates and that date should have maximum common hour.
So the sample output should look something like this.
common_data = {
date: "2021-07-15T12:18:12.223Z",
time: "30",
hours: "8:30AM"
}
I looked up at other answers and tried something like this:
merged all the arrays and
let result = merged_slots_array.shift().filter(function(v) {
return merged_slots_array.every(function(a) {
const matchDate = a.date === v.date;
const getMatchTime = a.hours.shift().filter(function(x) {
return v.hours.every(function(t) {
return x.indexOf(t) !== -1;
})
});
return matchDate && getMatchTime
});
});
but getting error merged_slots_array.shift(...).filter is not a function
After concatenating the arrays, finding the max common hour can be done through a filter that only keeps duplicates, then gets sorted. Once we have that, we can query each array to make sure it contains the max hour, then extract the max date and time. My output was slightly different than yours because i filtered for the max time, hour and date
array1 = [{
_id: "60f027f98b55eb2df1f36c04",
date: "2021-07-15T12:18:12.223Z",
time: "30",
hours: ["8:00 AM", "8:30 AM"]
}]
array2 = [{
_id: "60f027f98b55eb2df1f36c05",
date: "2021-07-15T12:18:12.223Z",
time: "60",
hours: ["7:30 AM", "8:30 AM", "9:30AM"]
}]
array3 = [{
_id: "60f027f98b55eb2df1f36c06",
date: "2021-07-16T12:12:12.223Z",
time: "30",
hours: ["7:00 AM", "8:30 AM"]
}]
const getCommon = (arrays) => {
let group = [].concat.apply([], [...arrays])
let hour = group.map(e=>e.hours).flat().filter((e,i,a) => a.indexOf(e) !== i).sort((a,b) => a.localeCompare(b))[0]
let common = group.filter(e=>e.hours.includes(hour))
let time = Math.max(...common.map(e => +e.time))
let date = common.map(e => e.date).sort((a,b) => new Date(b) - new Date(a))[0];
return {date: date, time: time, hours: [hour]}
}
let arg = []
arg.push(array1)
arg.push(array2)
arg.push(array3)
console.log(getCommon(arg))
TS Playground
I have the below array:
var data = [
{ "id":"id1", "key":"2020-07-15T06:32:44.08Z", "value":["E19","on"] },
{ "id":"id2", "key":"2020-07-15T06:32:44.08Z", "value":["E20","on"] },
{ "id":"id3", "key":"2020-07-15T06:32:44.08Z", "value":["E21","off"] },
{ "id":"id1", "key":"2020-07-15T06:33:44.08Z", "value":["E19","on"] },
{ "id":"id4", "key":"2020-07-15T06:34:44.08Z", "value":["E19","faulty"] },
{ "id":"id5", "key":"2020-07-15T06:35:44.08Z", "value":["E19","on"] }
];
I want this data to be converted to the below form to be used on Google charts:
var expectedData = [
["time","on","off","faulty"],
["06:32:44",2,1,0],
["06:33:44",2,1,0], //here the count is same because E19 is only records for this time which is
//already marked as 'on' in the before time stamp. Hence no change is required.
["06:34:44",1,1,1], //E19 has been changed to 'faulty', hence 'on' is reduced by 1 and 'faulty'
//increased by 1
["06:35:44",2,1,0] //E19 is changed back to 'on' hence 'on' is increased by 1 and 'faulty'
//reduced by 1
];
Can someone please help me with javascript code to sort this data to be used in my React Google charts?
I have written the below code so far:
const data = [
{ "id":"id1", "key":"2020-07-15T06:32:44.08Z", "value":["GigabyteEthernet4/0/19","on"] },
{ "id":"id2", "key":"2020-07-15T06:32:44.08Z", "value":["GigabyteEthernet4/0/20","on"] },
{ "id":"id3", "key":"2020-07-15T06:32:44.08Z", "value":["GigabyteEthernet4/0/21","off"] },
{ "id":"id1", "key":"2020-07-15T06:33:44.08Z", "value":["GigabyteEthernet4/0/19","on"] },
{ "id":"id4", "key":"2020-07-15T06:34:44.08Z", "value":["GigabyteEthernet4/0/19","faulty"] },
{ "id":"id5", "key":"2020-07-15T06:35:44.08Z", "value":["GigabyteEthernet4/0/19","on"] }
];
// var poeObj = new Object();
let t;
var newArray= [];
var newData = data.map((item,el)=>{
t= new Date(item.key);
var poeObj = Object.assign({},el)
poeObj.time= t.toLocaleTimeString();
poeObj.intfName= item.value[0];
poeObj.state= item.value[1];
if(poeObj.intfName)
console.log(poeObj);
return poeObj;
})
console.log(newData)
var newData1 = [
{time: "12:02:44 PM", intfName: "GigabyteEthernet4/0/19", state: "on"},
{time: "12:02:44 PM", intfName: "GigabyteEthernet4/0/20", state: "on"},
{time: "12:02:44 PM", intfName: "GigabyteEthernet4/0/21", state: "off"},
{time: "12:03:44 PM", intfName: "GigabyteEthernet4/0/19", state: "on"},
{time: "12:04:44 PM", intfName: "GigabyteEthernet4/0/19", state: "faulty"},
{time: "12:05:44 PM", intfName: "GigabyteEthernet4/0/19", state: "on"}
]
var uniqueData = newData1.reduce((arr,item)=>{
var newArr = [];
newArr.push(item.time, item.intfName, item.state);
console.log(newArr)
arr.push(newArr)
return arr;
},[])
console.log(uniqueData)
//uniqueData= [
["12:02:44 PM", "GigabyteEthernet4/0/19", "on"],
["12:02:44 PM", "GigabyteEthernet4/0/20", "on"],
["12:02:44 PM", "GigabyteEthernet4/0/21", "off"],
["12:03:44 PM", "GigabyteEthernet4/0/19", "on"],
["12:04:44 PM", "GigabyteEthernet4/0/19", "faulty"],
["12:05:44 PM", "GigabyteEthernet4/0/19", "on"]
];
After all these code, I have got the formatted array as the above 'uniqueData'. But not sure if this is the efficient way. Although, I idn't reach my final expected output which is 'expectedData' mentioned in the begining. Can some one please advise me on this?
You can transform the content of your item in an array by using Array map function.
If I have the following:
var data = [
{ "id":"1", "title":"Lorem ipsum" },
{ "id":"2", "title":"Test title" },
{ "id":"3", "title":"another title" },
];
I can do:
// .map will traverse each item and we pass a function on how we want to deal with new item structure
data.map((item) => {
// I will convert individual item to this format: Array[id, title]
return [item.id, item.title]
})
This will return
[
[1, "Lorem ipsum"],
[2, "Test title"],
[3, "another title"],
]
In your question you have a different item structure in your array ["time","on","off","faulty"]
by getting the output from .map you just append using .splice ["time","on","off","faulty"] from your .map result.
// This will append ["time","on","off","faulty"] in the first index of array
result.splice(0, 0, ["time","on","off","faulty"])
Using reduce is also possible
I can do:
// Reduce also works by merging items, it can take two parameters (function, initial value)
data.reduce((accumulated, currentItem) => {
accumulated.push([currentItem.id, currentItem.title])
}, [["time","on","off","faulty"]])
This will have similar output with .map, the difference is you can put ahead the ["time","on","off","faulty"] in your new array without doing splice.
var arr = [{"Event_code":"AB-001","Interest_area":"Arts","Start_time":"9:00 AM","End_time":"3:00 PM","Session_type":"Course information session"},{"Event_code":"AB-002","Interest_area":"Arts","Start_time":"12:30 PM","End_time":"1:00 PM","Session_type":"Course information session"},{"Event_code":"AB-003","Interest_area":"","Start_time":"9:00 AM","End_time":"3:00 PM","Session_type":"Course information session"},{"Event_code":"AB-004","Interest_area":"Business","Start_time":"10:30 AM","End_time":"11:00 AM","Session_type":"Course information session"},{"Event_code":"AB-005","Interest_area":"General Interest","Start_time":"9:00 AM","End_time":"1:30 PM","Session_type":"Experience"},{"Event_code":"AB-006","Interest_area":"Environment , Business ","Start_time":"11:00 AM","End_time":"11:30 AM","Session_type":"Course information session"}];
var st = {};
arr.forEach(o => {
if(st[o.Start_time]) o.clash = "yes";
else st[o.Start_time] = o.Start_time;
var diff = ( new Date("1970-1-1 " + o.End_time) - new Date("1970-1-1 " + o.Start_time) ) / 1000 / 60 / 60;
//console.log(diff); // hours
if (diff > 5){
o.duration = "Full day event";
}
});
console.log(arr);
What I am trying to do is add 2 key value pairs based on 2 conditions ..
Cond 1. Add "Clash":" Yes" if 2 events have a same start time
Cond 2: Add "Duration:"Full Day event" if "Start time" and "end time" have a difference of more than 5 hours.
The above code is not printing "clash":"Yes" pair.
This question has helped me greatly with Condition 1. I just want to add Condition 2 now.
For setting clash, you could take an object with start time and the actual index.
If another event starts at the time, set clash to both of the objects.
var array = [{ Event_code: "AB-001", Interest_area: "Arts", Start_time: "9:00 AM", End_time: "3:00 PM", Session_type: "Course information session" }, { Event_code: "AB-002", Interest_area: "Arts", Start_time: "12:30 PM", End_time: "1:00 PM", Session_type: "Course information session" }, { Event_code: "AB-003", Interest_area: "", Start_time: "9:00 AM", End_time: "3:00 PM", Session_type: "Course information session" }, { Event_code: "AB-004", Interest_area: "Business", Start_time: "10:30 AM", End_time: "11:00 AM", Session_type: "Course information session" }, { Event_code: "AB-005", Interest_area: "General Interest", Start_time: "9:00 AM", End_time: "1:30 PM", Session_type: "Experience" }, { Event_code: "AB-006", Interest_area: "Environment, Business", Start_time: "11:00 AM", End_time: "11:30 AM", Session_type: "Course information session" }],
clash = Object.create(null);
array.forEach((o, i, a) => {
var diff = (new Date("1970-1-1 " + o.End_time) - new Date("1970-1-1 " + o.Start_time)) / 1000 / 60 / 60;
//console.log(diff); // hours
if (diff > 5) {
o.duration = "Full day event";
}
if (o.Start_time in clash) {
a[clash[o.Start_time]].clash = true; // set first found
o.clash = true; // set actual item
return;
}
clash[o.Start_time] = i; // save index
});
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I changed your code a bit and here is new working code
I have the following code.
const timeLabels = [
{ name: "1:00 AM", present: true, label: ["1:00", "2:00"], value: "1:00" },
{ name: "2:00 AM", present: true, label: ["2:00", "3:00"], value: "2:00"},
{ name: "3:00 AM", present: true, label: ["3:00", "4:00"], value: "3:00" },
];
const targetedTimes = [["0:00", "1:00"], ["1:00", "2:00"]]
let actualTime = [];
console.log("getting time");
console.log("start: the actualTime is", actualTime);
for (var j = 0; j < timeLabels.length; j++) {
console.log("x");
var currItem = timeLabels[j];
var label = JSON.stringify(currItem.label);
var adTime = JSON.stringify(targetedTimes);
if (adTime.indexOf(label) >= 0) {
currItem.present = true;
} else {
currItem.present = false;
}
console.log("the current item is", currItem);
actualTime.push(currItem);
console.log("The actual time is", actualTime);
}
On the FIRST iteration, the currItem is
{name: "1:00 AM", present: true, label: Array(2), value: "1:00"}
But the actualTime is
[{name: "1:00 AM", present: true, label: Array(2), value: "1:00"},
{name: "2:00 AM", present: false, label: Array(2), value: "2:00"},
{name: "3:00 AM", present: false, label: Array(2), value: "3:00"}]
Why would the actualTime list have three values when I only append 1 on the first iteration?
What is happening is that the console is printing a reference to the object (becuase arrays are a type of object in javascript), so by the time you print it and read it in the console, each console.log statement is pointing at the same final array, which is why the values is the same each time.
Have a look at this similar StackOverflow question for more insight.
I tried running your script on node and it printed out the array correctly on each iteration, with only one item in the first iteration, so your code is fine.
I'm trying to write a javascript function to merge days with similar opening hours of a store together. For example, if we have:
"hours": [
"Friday 11:00am - 3:00pm, 5:00pm - 10:00pm",
"Monday 11:00am - 3:00pm, 5:00pm - 9:30pm",
"Saturday 12:00pm - 10:00pm",
"Sunday 12:00pm - 9:30pm",
"Thursday 11:00am - 3:00pm, 5:00pm - 9:30pm",
"Tuesday 11:00am - 3:00pm, 5:00pm - 9:30pm",
"Wednesday 11:00am - 3:00pm, 5:00pm - 9:30pm"
],
I want the code to simplify it to:
"hours": [
"Mo-Sa 11:00-14:30",
"Mo-Th 17:00-21:30",
"Fr-Sa 17:00-22:00"
],
Is there a way of accomplishing this without a long list of if/else or case statements?
Go functional and save a lot of mess.
Assuming that this is your data:
var data = [
{day: "Mon", open: 900, close: 1700},
{day: "Tue", open: 900, close: 1700},
{day: "Wed", open: 700, close: 1700},
{day: "Thu", open: 900, close: 1700},
{day: "Fri", open: 900, close: 1700},
{day: "Sat", open: 900, close: 1900},
{day: "Sun", open: 900, close: 1900},
];
You can simply reduce the array to a merged array in 6 lines of code:
var merged = data.reduce(function(preVal, curVal) {
var last = preVal[preVal.length - 1];
if (last && last.open == curVal.open && last.close == curVal.close) {
last.endDay = curVal.day;
} else {
preVal.push(curVal);
}
return preVal;
}, []);
And just in case for debugging:
for (var i in merged) {
var m = merged[i];
var endDay = m.endDay ? " to " + m.endDay : "";
console.log(m.day + endDay + " " + m.open + "-" + m.close);
}
BONUS Now, if you have to convert merged into a different format (e.g., something that you need to print on the screen) you can go functional again and map the merged into whatever format you want:
var mergedNewFormat = merged.map(function(v) {
return {
days: [v.day, v.endDay ? v.endDay : v.day],
hours: [v.open, v.close],
};
});
I would suggest breaking your data down into a more structured format than what you currently have specified in your comments such as:
var data = [
{ day: "Mon", hours: "11:00 AM to 10:30 PM" },
{ day: "Thu", hours: "11:00 AM to 10:30 PM" },
{ day: "Tue", hours: "11:00 AM to 10:30 PM" },
{ day: "Wed", hours: "11:00 AM to 10:32 PM" },
{ day: "Fri", hours: "11:00 AM to 10:00 PM" },
{ day: "Sat", hours: "11:00 AM to 10:00 PM" },
{ day: "Sun", hours: "11:00 AM to 10:30 PM" }
];
Now you can iterate over the days and group by identical hours like this:
function collapseHours(data) {
var collapsed = [];
var idx = -1;
for(var i=0; i<data.length; i++) {
var day = data[i];
if(idx == -1 || collapsed[idx].hours != day.hours) {
collapsed.push({days:[day.day],hours:day.hours});
idx++;
} else {
collapsed[idx].days.push(day.day);
}
}
return collapsed;
}
This collapseHours(data) would produce the following:
[
{"days":["Mon","Thu","Tue"],"hours":"11:00 AM to 10:30 PM"},
{"days":["Wed"],"hours":"11:00 AM to 10:32 PM"},
{"days":["Fri","Sat"],"hours":"11:00 AM to 10:00 PM"},
{"days":["Sun"],"hours":"11:00 AM to 10:30 PM"}
];
Now you can pretty print your hours like this:
function prettyPrintHours(collapsed) {
var lines = [];
for(var i=0; i<collapsed.length; i++) {
var line = collapsed[i];
var days = line.days;
if(days.length == 1) {
lines.push(days[0]+" "+line.hours);
} else {
lines.push(days[0]+"-"+days[days.length-1]+" "+line.hours);
}
}
return lines;
}
Which will produce:
[
"Mon-Tue 11:00 AM to 10:30 PM",
"Wed 11:00 AM to 10:32 PM",
"Fri-Sat 11:00 AM to 10:00 PM",
"Sun 11:00 AM to 10:30 PM"
]
Given these two functions it should be relatively simple to customize the data format and output formatting to your exact needs.