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
}
})
Related
I have the code to generate a random number and it seemes to be cycling back and forth between 1 or 2.
const isDnaUnique = (_DnaList = [], _dna = []) => { let foundDna =
_DnaList.find((i) => i.join("") === _dna.join("")); return foundDna == undefined ? true : false; };
const createDna = (_races, _race) => { let randNum = [];
_races[_race].layers.forEach((layer) => {
let randElementNum = Math.floor(Math.random() * 100) + 1;
let num = 0;
layer.elements.forEach((element) => {
if (randElementNum >= 100 - element.weight) {
num = element.id;
}
});
randNum.push(num); }); return randNum; };
My issue is the random number generator keeps only returning to values instead of cycling through all of them.
{
name: "Eyes",
elements: [
{
id: 0,
name: "E1",
path: `${dir}/3-eyes/E1.png`,
weight: 25,
},
{
id: 1,
name: "E2",
path: `${dir}/3-eyes/E2.png`,
weight: 25,
},
{
id: 2,
name: "E3",
path: `${dir}/3-eyes/E3.png`,
weight: 25,
},
{
id: 3,
name: "E4",
path: `${dir}/3-eyes/E4.png`,
weight: 25,
},
],
position: { x: 0, y: 0 },
size: { width: width, height: height },
},
Your results are exactly what I would expect. Let's take a look.
Your randElementNum is going to be a number from 1 to 100. All four of your elements have weight of 25. You are running through the loop for all of the elements every time. So, if the number is less than 75 (100-25), then the if statement never fires, and num will be 0. If the number is greater than or equal to 75, then the if statement fires all four times, and you'll end up with element #3. There are no other possibilities.
The next big problem is that "forEach" is the wrong tool. I've shown you how to make it work below, but you really should be using an old-fashioned "for" loop, so you can break the loop once you find an answer.
I'm not sure what effect you were trying for, but this is certainly not what you intended. Based on the name weight, were you trying to have each element get picked 25% of the time? You can do that with something like this:
const createDna = () => {
let randElementNum = Math.floor(Math.random() * 100);
console.log( randElementNum );
let num = -1;
layer.elements.forEach((element) => {
if( num >= 0 )
return;
if (randElementNum < element.weight)
{
num = element.id;
return;
}
randElementNum -= element.weight;
});
return num;
};
I'm trying to remove the object that matches my if statement
my array:
[
TextRow {
id: 4,
user_gender: 'Male',
user_tags: '[]',
user_birth: 26,
user_lat: '34.03569255690516',
user_lng: '-6.828115666526287',
user_current_occupancy: 'None',
user_biography: null,
set_from_map: 1,
info_verified: 0
},
TextRow {
id: 5,
user_gender: 'Male',
user_relationship: 'Single',
user_tags: '[]',
user_birth: 19,
user_lat: '32.8811',
user_lng: '-6.9063',
user_current_occupancy: 'None',
user_biography: null,
set_from_map: 1,
info_verified: 0
}
]
Here is a code snippet:
in distance function, I'm calculating the destination between the user and other users that I'm having them in the data array
data.map((value, i) => {
const destination = parseFloat(
distance(lat, long, value.user_lat, value.user_lng).toFixed(2)
);
// age_range is an array that have the range of age for example[16,26]
if (
destination > location_range ||
value.user_birth < age_range[0] ||
value.user_birth > age_range[1]
) {
data.splice(i, 1);
i = i - 1;
} else value.destination = destination;
});
it didn't work for what I want, thank u in advance
const data = newData.filter(el => {
const destination = parseFloat(
distance(lat, long, el.user_lat, el.user_lng).toFixed(2)
);
console.log(
destination > location_range ||
el.user_birth < age_range[0] ||
el.user_birth > age_range[1]
);
return !(
destination > location_range ||
el.user_birth < age_range[0] ||
el.user_birth > age_range[1]
);
});
data.forEach(el => {
const destination = parseFloat(
distance(lat, long, el.user_lat, el.user_lng).toFixed(2)
);
el.destination = destination;
});
You can use data.filter instead of data.map
check this for more details https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
I have 2 arrays:
generated timestamps (30 min each (1800 difference in each timestamp)) from particular start hour to end hour for a day.
I get a booked slots response from the API response.
I need to merge both arrays to form the array of objects representing the available and booked slots:
let availableTimeslots = [
1559709000,
1559710800,
1559712600,
1559714400,
1559716200,
1559718000,
1559719800,
1559721600,
1559723400,
1559725200,
1559727000,
1559728800,
1559730600,
1559732400,
1559734200,
1559736000,
1559737800,
1559739600
];
let bookedTimeSlots = {
bookings: [
{
timestamp: {
from: 1559719800,
to: 1559723400
}
},
{
timestamp: {
from: 1559730600,
to: 1559732400
}
}
]
};
I need to create array of objects, something like:
[
{
available: true,
timeslots: [1559709000, 1559710800, 1559712600, 1559714400, 1559716200, 1559718000]
},
{
available: false,
timeslots: [1559719800, 1559721600, 1559723400]
},
{
available: true,
timeslots: [1559725200, 1559727000, 1559728800]
},
{
available: false,
timeslots: [1559730600, 1559732400]
},
{
available: true,
timeslots: [1559732400, 1559734200, 1559736000, 1559737800, 1559739600]
}
];
I am really confused on how to proceed with this
I am thinking on to replace the value in availableTimeslots with the desired booked slot object and later on all the non-object values with {available: true, timeslots: [...]}
bookedTimeSlots.bookings.map((bs, i)=> {
let ai = availableTimeslots.findIndex(bs.timestamp.from);
ai > -1 && (availableTimeslots[ai]={available: false, x : [..._.range(bs.timestamp.from, bs.timestamp.to, 1800)]});
})
Any help would be appreciated.
There's a lot of ways you could solve this. One way to simplify it is to take advantage of the fact that there's a known increment (1,800) between timeslots, so rather than trying slice up the array of timeslots, you can generate a new array of timeslots for each "chunk" given a start and end timeslot. In the below snippet you can see a basic recursive solution that takes this approach:
const INCREMENT = 1800;
// Utility function to generate an inclusive range
function rangeIncl(start, end, incr = INCREMENT) {
return start < end ? [start, ...rangeIncl(start + incr, end)] : [end];
}
function timeslotGroups(startTimeslot, endTimeslot, bookings) {
const [booking, ...restBookings] = bookings;
if (booking) {
if (startTimeslot < booking.from) {
// startTimeslot is before next booking.from; add available group
return [
{
available: true,
timeslots: rangeIncl(startTimeslot, booking.from - INCREMENT),
},
...timeslotGroups(booking.from, endTimeslot, bookings),
];
}
if (startTimeslot <= booking.to) {
// startTimeslot is between booking.from and .to; add not-available group
return [
{
available: false,
timeslots: rangeIncl(booking.from, booking.to),
},
...timeslotGroups(booking.to + INCREMENT, endTimeslot, restBookings),
];
}
// startTimeslot is after booking.to; try again with next booking
return timeslotGroups(startTimeslot, endTimeslot, restBookings);
}
// No more bookings; add final available group if there are any
// timeslots left
return startTimeslot < endTimeslot ? [
{
available: true,
timeslots: rangeIncl(startTimeslot, endTimeslot),
},
] : [];
}
const availableTimeslots = [
1559709000, 1559710800, 1559712600, 1559714400, 1559716200, 1559718000,
1559719800, 1559721600, 1559723400, 1559725200, 1559727000, 1559728800,
1559730600, 1559732400, 1559734200, 1559736000, 1559737800, 1559739600,
];
const bookedTimeslots = {
bookings: [
{ timestamp: { from: 1559719800, to: 1559723400 }},
{ timestamp: { from: 1559730600, to: 1559732400 }},
],
};
const firstTimeslot = availableTimeslots[0];
const lastTimeslot = availableTimeslots[availableTimeslots.length - 1];
// Bookings will be easier to work with as an array of { from, to } objects
const bookings = bookedTimeslots.bookings.map(booking => booking.
timestamp);
const groups = timeslotGroups(firstTimeslot, lastTimeslot, bookings);
console.log(groups);
Note that this code assumes that bookings will be in chronological order.
I did it with something like this: https://jsfiddle.net/saurabhsharma/a6qoyfhd/
let availableTimeslots = [
1559709000,
1559710800,
1559712600,
1559714400,
1559716200,
1559718000,
1559719800,
1559721600,
1559723400,
1559725200,
1559727000,
1559728800,
1559730600,
1559732400,
1559734200,
1559736000,
1559737800,
1559739600
];
let parsedArr = [];
let bookedTimeSlots = {
bookings: [{
timestamp: {
from: 1559719800,
to: 1559723400
}
},
{
timestamp: {
from: 1559730600,
to: 1559732400
}
}
]
};
/* parsedArr = availableTimeslots.map((ts, i) => {
return bookedTimeSlots.bookings.map((bs, n)=> {
let x = [];
if(ts<bs.timestamp.from) {
x.push(ts);
} else { return {available: true, timeslots: [...x]}}
})
}) */
bookedTimeSlots.bookings.map((bs, i) => {
let ai = availableTimeslots.indexOf(bs.timestamp.from);
if (ai > -1) {
let range = [..._.range(bs.timestamp.from, bs.timestamp.to, 1800)]
availableTimeslots[ai] = {
available: false,
timestamp: [...range]
};
availableTimeslots.splice(ai + 1, range.length - 1);
}
})
console.log("availableTimeSlot", availableTimeslots);
let tempArr = [];
let startIndex = '';
let timeStampParsed = [...availableTimeslots];
while(!timeStampParsed.every((ts)=>typeof ts == 'object')) {
timeStampParsed.map((ts, i) => {
if (typeof ts != "object") {
tempArr.push(ts);
startIndex === '' && (startIndex = i);
//Case i reached the last index
if (i == timeStampParsed.length - 1) {
let range = [..._.range(timeStampParsed[startIndex], timeStampParsed[i]+1800, 1800)];
console.log(range);
timeStampParsed[startIndex] = {
available: true,
timestamp: [...range]
};
timeStampParsed.splice(startIndex + 1, range.length);
tempArr = [];
startIndex = '';
}
} else {
if (tempArr.length > 0 && startIndex !== '') {
let range = [..._.range(timeStampParsed[startIndex], timeStampParsed[i-1], 1800)];
timeStampParsed[startIndex] = {
available: true,
timestamp: [...range]
};
timeStampParsed.splice(startIndex+1, range.length);
tempArr = [];
startIndex = '';
}
}
})
}
console.log("TIMESTAMP PARSED =>", timeStampParsed);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Please suggest a better way to do it.
how to count the value of object in new object values
lets say that i have json like this :
let data = [{
no: 3,
name: 'drink'
},
{
no: 90,
name: 'eat'
},
{
no: 20,
name: 'swim'
}
];
if i have the user pick no in arrays : [3,3,3,3,3,3,3,3,3,3,3,90,20,20,20,20]
so the output should be an array
[
{
num: 3,
total: 11
},
{
num: 90,
total: 1
},
{
num:20,
total: 4
}
];
I would like to know how to do this with a for/of loop
Here is the code I've attempted:
let obj = [];
for (i of arr){
for (j of data){
let innerObj={};
innerObj.num = i
obj.push(innerObj)
}
}
const data = [{"no":3,"name":"drink"},{"no":90,"name":"eat"},{"no":20,"name":"swim"}];
const arr = [3,3,3,3,3,3,3,3,3,3,3,20,20,20,20,80,80];
const lookup = {};
// Loop over the duplicate array and create an
// object that contains the totals
for (let el of arr) {
// If the key doesn't exist set it to zero,
// otherwise add 1 to it
lookup[el] = (lookup[el] || 0) + 1;
}
const out = [];
// Then loop over the data updating the objects
// with the totals found in the lookup object
for (let obj of data) {
lookup[obj.no] && out.push({
no: obj.no,
total: lookup[obj.no]
});
}
document.querySelector('#lookup').textContent = JSON.stringify(lookup, null, 2);
document.querySelector('#out').textContent = JSON.stringify(out, null, 2);
<h3>Lookup output</h3>
<pre id="lookup"></pre>
<h3>Main output</h3>
<pre id="out"></pre>
Perhaps something like this? You can map the existing data array and attach filtered array counts to each array object.
let data = [
{
no: 3,
name: 'drink'
},
{
no:90,
name: 'eat'
},
{
no:20,
name: 'swim'
}
]
const test = [3,3,3,3,3,3,3,3,3,3,3,90,20,20,20,20]
const result = data.map((item) => {
return {
num: item.no,
total: test.filter(i => i === item.no).length // filters number array and then checks length
}
})
You can check next approach using a single for/of loop. But first I have to create a Set with valid ids, so I can discard noise data from the test array:
const data = [
{no: 3, name: 'drink'},
{no: 90, name: 'eat'},
{no: 20, name: 'swim'}
];
const userArr = [3,3,3,3,3,3,3,3,7,7,9,9,3,3,3,90,20,20,20,20];
let ids = new Set(data.map(x => x.no));
let newArr = [];
for (i of userArr)
{
let found = newArr.findIndex(x => x.num === i)
if (found >= 0)
newArr[found].total += 1;
else
ids.has(i) && newArr.push({num: i, total: 1});
}
console.log(newArr);
I have an array that is constantly updated and accordingly it is necessary to update its grouping. Example of an array:
[
{
"price": 2419.62,
"amount": 0.0266
},
{
"price": 1927.52,
"amount": 0.0217
},
...
]
I tried different options. At the moment this option is the fastest:
const points = [
{
"price": 2419.62,
"amount": 0.0266
},
{
"price": 1927.52,
"amount": 0.0217
},
...
];
const range = 500;
const spread = 1800;
const countGroup = 250;
const sizeUnitGroup = range / countGroup;
const groups = {};
for (let i = 0; i < countGroup; i++){
groups[i] = [];
try {
points.forEach((item, id) => {
if (item.price > spread + (i*sizeUnitGroup) && item.price <= spread + (i*sizeUnitGroup + sizeUnitGroup)){
groups[i].push(item);
points.splice(id, 1);
}
if (item.price > (spread + (i*sizeUnitGroup + sizeUnitGroup))) throw BreakException;
});
} catch (e) {
}
}
But even so, this function works for too long. Any ideas how this can be optimized?
You could calculate the interval for pushing the value to the wanted slot.
var points = [
{ price: 2419.62, amount: 0.0266 },
{ price: 1927.52, amount: 0.0217 },
{ price: 1800, amount: 0.07 }, // -1 not in result
{ price: 1800.000000000001, amount: 0.07 }, // 0
{ price: 1802, amount: 0.07 }, // 0
],
range = 500,
spread = 1800,
countGroup = 250,
sizeUnitGroup = range / countGroup,
groups = {};
points.forEach((item, id) => {
var i = Math.ceil((item.price - spread- sizeUnitGroup) / sizeUnitGroup);
if (i >= 0 && i < countGroup) {
groups[i] = groups[i] || [];
groups[i].push(item);
}
});
console.log(groups);
.as-console-wrapper { max-height: 100% !important; top: 0; }