How to check the JavaScript array objects are overlapping - javascript

I have an array of objects containing start and end range.
var ranges = [{
start: 1,
end: 5
}]
I want to push an object like this without overlapping with the previous start and end range
{
start: 6,
end: 10
}
How to check new object overlapping with the existing objects
Edit:
{
start: 50,
end: 100
},
{
start: 11,
end: 49
}

Got the answer thanks everyone for your response.
let isValid = timeRanges.every(r => (r.begin != selected.begin && r.begin < selected.begin && selected.begin > r.end) && (r.end != selected.end && r.end < selected.begin && selected.end > r.end));

You can try this :
const ranges = [{
start: 1,
end: 5
}];
const rangeObj = {
start: 6,
end: 10
};
function checkRangeOverlap(obj) {
let res = ''
ranges.forEach((obj) => {
res = (obj.end > rangeObj.start) ? 'Overlaping': 'No Overlap';
});
return res;
}
console.log(checkRangeOverlap(rangeObj));

Related

How could I compute a list of "open hours" in javascript from a list of start and end times with overlaps?

I am trying to simplify a list of open times so that there are no overlaps/duplicate information showing (in javascript).
Here is an example of what I am trying to achieve:
The starting array would look something like this:
const mondayHours = [
{ start: "09:00", end: "14:00" },
{ start: "10:00", end: "15:00" },
{ start: "17:00", end: "23:00" },
];
And the data is currently displayed like:
Open: 9am-2pm, 10am-3pm, 5pm-11pm
I want the result to return an array for the total open hours like so:
const computedMondayHours = [
{ start: "09:00", end: "15:00" },
{ start: "17:00", end: "23:00" },
];
And so that the data will be displayed like:
Open: 9am-3pm, 5pm-11pm
I have found a solution online that returns the latest open times with the earliest close times, thinking I could convert it for my uses, but that has not worked at all:
const hours = [{
start: "09:00",
end: "14:00"
},
{
start: "10:00",
end: "15:00"
},
{
start: "17:00",
end: "23:00"
}
]
const isBetween = (value, start, end) => value > start && value < end
const computeOpenHours = (dayHours) => {
const index = {}
dayHours.forEach(({
start: aStart,
end: aEnd
}) => {
dayHours.forEach(({
start: bStart,
end: bEnd
}) => {
aStart = isBetween(bStart, aStart, aEnd) && bStart > aStart ? bStart : aStart
aEnd = isBetween(bEnd, aStart, aEnd) && bEnd < aEnd ? bEnd : aEnd
})
const key = `${aStart}-${aEnd}`
const value = {
start: aStart,
end: aEnd
}
index[key] = index[key] || value
})
return Object.keys(index).map(k => index[k])
}
console.log(computeOpenHours(hours))
You can reduce the hours and check if the current start is greater than the prev end time.
Note: This naïve algorithm assumes the input array is already sorted.
const calcTimeSlots = (workingHours) =>
workingHours.reduce((acc, { start, end }) => {
if (acc.length === 0) {
acc.push({ start, end });
} else {
const latest = acc[acc.length - 1];
if (parseTimeAsMillis(start) > parseTimeAsMillis(latest.end)) {
acc.push({ start, end });
} else if (parseTimeAsMillis(end) > parseTimeAsMillis(latest.end)) {
latest.end = end;
}
}
return acc;
}, []);
const parseTimeAsMillis = (str) =>
str.split(':')
.map((t, i, a) => parseInt(t) * 60 * (a.length - 1))
.reduce((total, curr) => total + curr);
const mondayHours = [
{ start: '09:00', end: '14:00' },
{ start: '10:00', end: '15:00' },
{ start: '17:00', end: '23:00' }
];
const tuesdayHours = [
{ start: '09:00', end: '14:00' },
{ start: '10:00', end: '11:00' }
];
console.log(calcTimeSlots(mondayHours));
console.log(calcTimeSlots(tuesdayHours));
.as-console-wrapper { top: 0; max-height: 100% !important; }
Also, here is a related question that I previously answered that may help:
"Moment.js - Duration within business/open/shift hours?"
const hours = [{"start":"09:00","end":"14:00"},
{"start":"10:00","end":"15:00"},
{"start":"17:00","end":"23:00"}]
// returns -ve if a<b, 0 if a=b, +ve if a>b
function cmp(a, b) {
return a.replace(':','') - b.replace(':','')
}
function mergeIfOverlap({start:s1, end:e1}, {start:s2, end:e2}) {
return cmp(s1,s2)<=0 && cmp(e1,s2)>=0
&& {start: s1, end: cmp(e1,e2)>=0 ? e1 : e2}
}
const result = [...hours].sort(({start:a},{start:b})=>cmp(a,b))
.reduce((a,c,_,x,y)=>(
x=a.findIndex(i => y=mergeIfOverlap(i,c)||mergeIfOverlap(c,i)),
y && (a[x]=y) || a.push(c), a), [])
console.log(result)

How to map array elements in JavaScript

Only elements that have a value greater than or equal to the threshold must be kept in the array. Then a new array will have to be created which will contain several objects. Each of these objects will have two properties, the start and the end.
If there are several elements in a row (which have a timestamp 10 minutes apart), they will be grouped in the same object. Where the start value will be the timestamp of the first element and the end value will be the timestamp value of the last element of the group plus 10 min.
If there are not several elements followed, the start value will be the timestamp and the end will be the timestamp plus 10 minutes.
const data = [{
timestamp: '2021-11-23T14:00:00+0000',
amount: 21
},
{
timestamp: '2021-11-23T14:10:00+0000',
amount: 27
},
{
timestamp: '2021-11-23T14:20:00+0000',
amount: 31
},
{
timestamp: '2021-11-23T14:30:00+0000',
amount: 29
},
{
timestamp: '2021-11-23T14:40:00+0000',
amount: 18
},
{
timestamp: '2021-11-23T14:50:00+0000',
amount: 17
},
{
timestamp: '2021-11-23T15:00:00+0000',
amount: 25
},
{
timestamp: '2021-11-23T15:10:00+0000',
amount: 21
}
]
const threshold = 25
const aboveThreshold = data.filter(element => element.amount >= threshold)
const workSchedule = []
for (let i = 0; i < aboveThreshold.length; i++) {
if (i === 0) {
workSchedule.push({
start: aboveThreshold[i].timestamp,
end: aboveThreshold[i + 1].timestamp
})
}
if (i > 0 && i < aboveThreshold.length - 1) {
if (aboveThreshold[i].timestamp.slice(11, 13) === aboveThreshold[i + 1].timestamp.slice(11, 13)) {
workSchedule.push({
start: aboveThreshold[i].timestamp,
end: aboveThreshold[i + 1].timestamp
})
}
}
if (i === aboveThreshold.length - 1) {
workSchedule.push({
start: aboveThreshold[i].timestamp,
end: aboveThreshold[i].timestamp
})
}
}
console.log(workSchedule)
But the end result I want is the following:
[
{
start: '2021-11-23T14:10:00+0000',
end: '2021-11-23T14:40:00+0000'
},
{
start: '2021-11-23T15:00:00+0000',
end: '2021-11-23T15:10:00+0000'
}
]
I hope I was clear 😬 and is there a simpler and easier to understand/read approach than what I've done so far?
You can apply a simple reduce function to get the result you want with a little bit of help from Date object. Here is a solution:
const aboveThreshold = data.filter(element => element.amount >= threshold);
const nws = aboveThreshold.reduce((acc, v) => {
const end = new Date(Date.parse(v.timestamp) + 600000);
if (acc.length === 0) return [{ start: v.timestamp, end: end.toISOString() }];
let diff = Date.parse(v.timestamp) - Date.parse(acc[acc.length - 1].end);
// checks if the difference is less than 10 minutes
if (diff <= 10 * 60 * 1000) {
acc[acc.length - 1].end = end.toISOString();
} else {
acc.push({ start: v.timestamp, end: end.toISOString() });
}
return acc
}, []);
Check out Reduce Documentation.
This is the result it gives with your data
[{
end: "2021-11-23T14:40:00.000Z",
start: "2021-11-23T14:10:00+0000"
}, {
end: "2021-11-23T15:10:00.000Z",
start: "2021-11-23T15:00:00+0000"
}]

How to update value in array based on values in another array?

I am having two array like this,
let array1 = [
{
"id": 23,
"name": "Telangana",
}
]
Here i need to update array2 color value inside properties based on array1 numberOfProjects value inside latestMetric. As u can see that in both arrays stateId and id are same.If numberOfProjects value is in the range 1 - 1000. I need to update the color value as 1. then numberOfProjects value is in the range 1000 - 2000. I need to update the color value as 2.so on. I dont know how to achieve this. I tried to map those two arrays and can able to get the ID's.But i dont know how to compare them and update the value . Pleas help me.Thanks in advance
You can do like this
let updatedArr2 = [];
function updateArr2(arr2values, colorValue) {
let updatedProperties = { ...arr2values.properties, color: colorValue };
arr2values.properties = updatedProperties;
updatedArr2.push(arr2values);
}
array2.map(arr2values =>
array1.map(arr1values => {
if (arr2values.properties.stateId === arr1values.latestMetric.stateId) {
if (
arr1values.latestMetric.numberOfProjects >= 1 &&
arr1values.latestMetric.numberOfProjects <= 1000
) {
updateArr2(arr2values, 1);
} else if (
arr2values.latestMetric.numberOfProjects >= 1000 &&
arr2values.latestMetric.numberOfProjects <= 2000
) {
updateArr2(arr2values, 2);
}
}
})
);
console.log(updatedArr2);
You could loop through each object in array1 and then check if there's any object in array2 that matches the stateId, if so, then check the number of projects in the array1 object and change the color of the object in array2 that has the same stateId, something like:
array1.forEach((o) => {
let matches = array2.filter(
(o2) => o2.properties.stateId === o.latestMetric.stateId
);
let projects = o.latestMetric.numberOfProjects;
for (let match of matches) {
if (projects > 1 && projects < 1000) {
match.properties.color = 1;
} else if (projects >= 1000 && projects < 2000) {
match.properties.color = 2;
}
}
});
let array1 = [
{
id: 23,
name: "Telangana",
code: "lnn",
regionId: 1,
isActive: true,
latitude: 17.8495919,
longitude: 79.1151663,
latestMetric: {
stateId: 23,
year: 0,
constructionValueInMn: 84623,
constructionAreaInMnSqft: 32,
numberOfProjects: 406,
noOfCompletedProjects: 19,
noOfOngoingProjects: 387,
noOfUpcomingProjects: 0,
growthRate: 0,
averagePricePerSqftInRs: 0,
totalAreaInMnSqft: 71,
overAllAvgSqft: 0,
eachVariantAvgSqft: 0,
noOfTypeOfVariant: 0,
projectCompletionCycle: 0,
},
createdAt: "2020-04-21T00:35:11.684134",
updatedAt: "2020-04-21T00:35:11.684134",
},
];
let array2 = [
{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
[77.19721, 28.861519],
[77.203836, 28.86004],
],
],
},
properties: {
cartodb_id: 26,
state_code: 7,
st_nm: "NCT of Delhi",
color: 2,
id: 23,
stateId: 23,
},
},
];
array1.forEach((o) => {
let matches = array2.filter(
(o2) => o2.properties.stateId === o.latestMetric.stateId
);
let projects = o.latestMetric.numberOfProjects;
for (let match of matches) {
if (projects > 1 && projects < 1000) {
match.properties.color = 1;
} else if (projects >= 1000 && projects < 2000) {
match.properties.color = 2;
}
}
});
console.log(array2);
Try this:
array2.map(arr2 => {
//Find to return the position when the id's are the same
const arr1 = array1.find(arr => arr.latestMetric.stateId == arr2.properties.id)
// If find was successful, do this
if (arr1) {
// Destructuring assignment to be easier to compare
const { numberOfProjects } = arr1.latestMetric
if (numberOfProjects >= 1 && numberOfProjects < 1000)
arr2.properties.color = 1
else if (numberOfProjects >= 1000 && numberOfProjects < 2000)
arr2.properties.color = 2
}
})

How do i loop through object and remove properties which are not equal to something

Below code removes hours and days properties.What I am trying to do is remove properties which are not equal to hours and days.How do I iterate properties and check if it's not equal then remove?
Object.keys(allcoursetimeobject).forEach(function(key) {
//this removes hours and days.I want to remove properties which are not equal to hours and days.
delete allcoursetimeobject[key].hours;
delete allcoursetimeobject[key].days;
});
Just repeat the loop
allcoursetimeobject = {
test1 : {
hours : 3,
days : 4,
something : 3,
},
test2 : {
hours : 3,
days : 4,
somethingElse : 5,
}
}
Object.keys(allcoursetimeobject).forEach(function(key) {
Object.keys(allcoursetimeobject[key]).forEach(function(secondKey){
if(allcoursetimeobject[key][secondKey] !== allcoursetimeobject[key].hours && allcoursetimeobject[key][secondKey] !== allcoursetimeobject[key].days){
delete allcoursetimeobject[key][secondKey];
}
});
});
console.log(allcoursetimeobject);
demo
You can use Object.keys() to iterate through keys of an object and then using array#includes you can check if a key exists in a given array. If found, delete it using delete.
const oldObject = { key1: { hours: 3, days: 4, prop1: 3, }, key2: { hours: 3, days: 4, prop2: 5, } };
Object.keys(oldObject).forEach(k => {
Object.keys(oldObject[k]).forEach(key => {
if(['hours','days'].includes(key)){
delete oldObject[k][key];
}
});
});
console.log(oldObject);
Assumptions:
You want to delete properties from objects within the allcoursetimeobject, based on the code snippet provided by you.
Then answer is:
var allcoursetimeobject = {
a: {
hours: 10,
days: 20,
test: "Delete This"
},
b: {
hours: 5,
days: 15,
test: "Delete This"
}
};
Object.keys(allcoursetimeobject).forEach(function(key) {
Object.keys(allcoursetimeobject[key]).forEach(function(k) {
if (k != "hours" && k != "days") {
delete allcoursetimeobject[key][k];
}
});
});
console.log(allcoursetimeobject);
Or Maybe, you want to delete properties in the allcoursetimeobject object itself
Then:
var allcoursetimeobject = {
hours: 10,
days: 20,
test: "Delete This"
};
Object.keys(allcoursetimeobject).forEach(function(key) {
if (key != "hours" && key != "days") {
delete allcoursetimeobject[key];
}
});
console.log(allcoursetimeobject);
Hope that helps!

Change index in array.map

I have a variable of the form:
var data=[
{
start:22,
end: 8
},
{
start:60,
end: 43
},
{
start: 35,
end: 55
},
{
start:25,
end:40
}
];
I want to map it to look like this
var newData = { 22:8, 60:43, 35:55, 25:40};
Is this possible? I mainly just want to use the start numbers as a key to access the end numbers without using search. I have tried to do this:
var mapData = data.map(function(data){
var x = {};
x[data.start]=data.end;
return x;
});
but it gives:
0
:
{22: 8}
1
:
{60: 43}
2
:
{35: 55}
3
:
{25: 40}
which means i have to use 0, 1,2, 3 as indices.
Only Array#map does not work in this case, because without post processing, you get a single array with objects. You need to combine all objects into a single object.
With Object.assign and spread syntax ..., you get a single array with all properties from the objects in the array.
var data = [{ start: 22, end: 8 }, { start: 60, end: 43 }, { start: 35, end: 55 }, { start: 25, end: 40 }],
result = Object.assign(...data.map(({ start, end }) => ({ [start]: end })));
console.log(result);
You can use array.reduce:
var data=[
{
start:22,
end: 8
},
{
start:60,
end: 43
},
{
start: 35,
end: 55
},
{
start:25,
end:40
}
];
var res = data.reduce((m, o) => {
m[o.start] = o.end;
return m;
}, {});
console.log(res);

Categories