How to find the index to be insterted in array of object.
I have array of Object.
var cordinate = [
[225, 242],
[405, 242],
[585, 242],
[765, 242],
[225, 325],
[405, 325],
[585, 325],
[765, 325],
[225, 408],
[405, 408],
[585, 408],
[765, 408]
]
Here i want to nearest element to be inserted
array which i want to insert
var extraEle = [404, 260]
How to detremine the exact index for the extraEle in cordinate.
Here is what I am trying
I am comparing y cordinate to get the nearest range and then comparing x cordinate with only y range to get index.
var yValue = [];
var diffVal = cordinate[0][1];
for(var i=0; i<cordinate.length;i ){
if (Math.abs(extraEle[1] - diffVal) > Math.abs(extraEle[1]- cordinate[i][1])){
diffVal = componentsPos[i][1];
}
}
var index;
yvalue = [];
for(var i=0; i<cordinate.length;i ){
if (cordinate[i][1] === diffVal){
yvalue.push(componentsPos[i]);
}
}
var diffValX = yvalue[0][0];
for(var i=0; i<yvalue.length;i ){
if (Math.abs(extraEle[0] - diffValX) > Math.abs(extraEle[0]- yvalue[i][0])){
diffValX = yvalue[i][0];
}
}
var indexValue = [diffValX,diffVal]
cordinate.indexOf(indexValue, 0)
Can we have something inbuilt or better approach than this. Note : This code is working code.
The output in my case will be 2 because 260(Y) will be in range of first 4 element and 404 (X) will come before third element.
After adding my cordinate should be like.
cordinate = [
[225, 242],
[405, 242],
[404, 260],
[585, 242],
[765, 242],
[225, 325],
[405, 325],
[585, 325],
[765, 325],
[225, 408],
[405, 408],
[585, 408],
[765, 408]
]
But precisely I need only index where I can insert.
CodePudding user response:
This might not be the most elegant solution, but it will determine the closest coordinate, by calculating the distance between the points and determining the closest one, then you can just splice
it into the array.
// Input coordinates
let coordinates =
[
[225, 242],
[405, 242],
[585, 242],
[765, 242],
[225, 325],
[405, 325],
[585, 325],
[765, 325],
[225, 408],
[405, 408],
[585, 408],
[765, 408]
];
// Add this to the array
let extraEle = [404, 260];
getClosestIndex(coordinates, extraEle).then((result) => {
coordinates.splice(result, 0, extraEle);
console.log(coordinates);
// Output
/*[
[225, 242],
[405, 242],
[404, 260]
[585, 242],
[765, 242],
[225, 325],
[405, 325],
[585, 325],
[765, 325],
[225, 408],
[405, 408],
[585, 408],
[765, 408]
]; */
});
function getClosestIndex(coords, targetCoords) {
return new Promise((resolve, reject) => {
let shortestDist = 999999999;
let shortestIndex = 0;
coords.forEach((coord, index) => {
let dist = Math.sqrt( Math.pow((coord[0]-targetCoords[0]), 2)
Math.pow((coord[1]-targetCoords[1]), 2));
if (dist < shortestDist) {
shortestDist = dist;
shortestIndex = index;
}
});
// To add it after the closest element
if (shortestIndex < coords.length - 1)
shortestIndex = 1;
resolve(shortestIndex);
});
}
CodePudding user response:
The logic as I understand is:
Find the sub-arrays that is closest in value of y
and then X
more accurately. Note: OP's example of desired output is wrong:
[405, 242], [404, 260], [585, 242],...
[404, 260]
should be placed before [405, 242]
.
In the example below:
- 2 array of arrays are created from x and y values.
[[x, (x - 404)],...] and [[y, (y - 260)],...]
Then each sub-array is sorted by index 1 and from that we derive the closest [x, y]
let coords = [[225,242],[405,242],[585,242],[765,242],[225,325],[405,325],[585,325],[765,325],[225,408],[405,408],[585,408],[765,408]];
let add = [404, 260];
const findRange = (array, xy) => {
let xArr = [];
let yArr = [];
for (let sub of array) {
xArr.push([sub[0], Math.abs(xy[0] - sub[0])]);
yArr.push([sub[1], Math.abs(xy[1] - sub[1])]);
}
let xRng = xArr.sort((a, b) => a[1] - b[1]);
let yRng = yArr.sort((a, b) => a[1] - b[1]);
let X = xRng[0][0];
let Y = yRng[0][0];
let closest = [X, Y];
let idx = array.flatMap((s, i) => closest[0] === s[0] && closest[1] === s[1] ? i : []);
if (X >= xy[0]) {
array.splice(idx, 0, xy);
} else {
array.splice(idx 1, 0, xy);
}
return array;
};
console.log(findRange(coords, add));
CodePudding user response:
Here is a funny solution.
Given a simple function that finds the closest value in an array, find the nearest Y value. Then all you have to do is add the new coordinate to the array and sort by Y then X column. When sorting the new coordinate treat its Y value as the nearest Y value.
let coords = [[225,242],[405,242],[585,242],[765,242],[225,325],[405,325],[585,325],[765,325],[225,408],[405,408],[585,408],[765,408]];
let add = [404, 260];
const closestValue = (array, goal) =>
array.reduce((prev, curr) =>
Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);
let nearestY = closestValue(coords.map(c => c[1]), add[1]);
coords.push(add);
coords.sort(function([a, b], [c, d]) {
if(b === add[1]){
b = nearestY;
} else if(d === add[1]){
d = nearestY;
}
return b - d || a - c
});
console.log(coords);
I believe the sort can be improved.