Related
I have 1D pointer array like below:
Darray = [{x: 334, y: 400.5}, {x: 237, y: 389},{x: 149, y: 387.5},{x: 55, y: 379.5},{x: 210, y: 301.5},{x: 48, y: 295.5},{x: 378.5, y: 224.5},{x: 283, y: 217.5},{x: 121.5, y: 211.5},{x: 198.5, y: 211.5},{x: 42.5, y: 201},{x: 33, y: 134},{x: 364, y: 142},{x: 268.5, y: 137},{x: 192, y: 136.5},{x: 106, y: 131.5},{x: 263.5, y: 68},{x: 182.5, y: 63.5},{x: 102.5, y: 61.5},{x: 344.5, y: 65.5},{x: 32, y: 52}]
//console.log(Darray)
const points = Darray.slice();
points.sort((a, b) => a.y - b.y);
console.log(points)
I want to convert this 1D array into 2D array based on the array row length. For example,
row_length = [5, 5, 5, 2, 4]
new_Darray = [[element[1,1],element[1,2], element[1,3], element[1,4], element[1,5],
[element[2,1],element[2,2], element[2,3], element[2,4], element[2,5],
[element[3,1],element[3,2], element[3,3], element[3,4], element[3,5],
[element[4,1],element[4,2],
[element[5,1],element[5,2], element[5,3], element[5,4], element[5,5]]
Here, element[i] represents {x:someValue, y:someValue}
Sorry, if I wrongly represented anything. Any help will be highly appreciated.
Using map, slice and temp variable, can be simplified to one-liner
const Darray = [
{ x: 334, y: 400.5 },
{ x: 237, y: 389 },
{ x: 149, y: 387.5 },
{ x: 55, y: 379.5 },
{ x: 210, y: 301.5 },
{ x: 48, y: 295.5 },
{ x: 378.5, y: 224.5 },
{ x: 283, y: 217.5 },
{ x: 121.5, y: 211.5 },
{ x: 198.5, y: 211.5 },
{ x: 42.5, y: 201 },
{ x: 33, y: 134 },
{ x: 364, y: 142 },
{ x: 268.5, y: 137 },
{ x: 192, y: 136.5 },
{ x: 106, y: 131.5 },
{ x: 263.5, y: 68 },
{ x: 182.5, y: 63.5 },
{ x: 102.5, y: 61.5 },
{ x: 344.5, y: 65.5 },
{ x: 32, y: 52 },
];
const points = Darray.slice();
points.sort((a, b) => a.y - b.y);
// console.log(points);
const row_length = [5, 5, 5, 2, 4];
let last = 0;
const output = row_length.map((len) => points.slice(last, (last += len)));
console.log(output);
This question already has answers here:
How to remove duplicates objects in array based on 2 properties?
(6 answers)
Closed 1 year ago.
I'm storing some coordinates in an array. It looks like this:
const coords = [{x: 260, y: 60}, {x: 180, y: 0}, {x: 180, y: 240}, {x: 360, y: 120}, {x: 180, y: 60}, {x: 180, y: 60}, {x: 180, y: 60}]
How can I filter this array so the objects are unique, meaning there are no duplicates of objects with same x and y value? Expected output should be:
const coords = [{x: 260, y: 60}, {x: 180, y: 0}, {x: 180, y: 240}, {x: 360, y: 120}, {x: 180, y: 60}]
I've seen some similar solutions, but they didn't really solve this problem.
I started with the following function
const output = Object.values(
coords.reduce( (c, e) => {
if (!c[e.x]) c[e.x] = e;
return c;
}, {})
but it only returns objects with different x values, so it just completely ommits y value.
One idea is to use a Set, map the x & y into a string, and then deserialize the Set to have unique x,y's..
eg..
const coords = [{x: 260, y: 60}, {x: 180, y: 0}, {x: 180, y: 240}, {x: 360, y: 120}, {x: 180, y: 60}, {x: 180, y: 60}, {x: 180, y: 60}];
const dedup = [...new Set(coords.map(m => `${m.x}:${m.y}`))].map(m => {
const [x,y] = m.split(':').map(n => n | 0);
return {x,y};
});
console.log(dedup);
We can use Array.reduce(),
along with a Map to get the required result.
We'd add each item to the map, using the concatenated x and y values as keys, then return the values() to get de-duplicated values.
This will have complexity of O(n), so it will be efficient for large arrays.
const coords = [{x: 260, y: 60}, {x: 180, y: 0}, {x: 180, y: 240}, {x: 360, y: 120}, {x: 180, y: 60}, {x: 180, y: 60}, {x: 180, y: 60}];
const dedup = [...coords.reduce((map, { x, y }) => {
return (map.set(`${x}-${y}`, { x, y }));
}, new Map()).values()];
console.log('De-duplicated:', dedup)
.as-console-wrapper { max-height: 100% !important; top: 0; }
Or with a regular object:
const coords = [{x: 260, y: 60}, {x: 180, y: 0}, {x: 180, y: 240}, {x: 360, y: 120}, {x: 180, y: 60}, {x: 180, y: 60}, {x: 180, y: 60}];
const dedup = Object.values(coords.reduce((acc, { x, y }) => {
return { ...acc, [`${x}-${y}`]: { x, y }}
}, {}));
console.log('De-duplicated:', dedup)
.as-console-wrapper { max-height: 100% !important; top: 0; }
A pretty inefficient (O(n^2)), but flexible and straightforward solution: You first define a function that checks if two coordinates are equal. Then you filter all elements which have an equal element at a later position in the array.
const coords = [{x: 260, y: 60}, {x: 180, y: 0}, {x: 180, y: 240}, {x: 360, y: 120}, {x: 180, y: 60}, {x: 180, y: 60}, {x: 180, y: 60}]
const customUnique = (arr, isEqual) => {
// filter elements where an equal element exists at an earlier position
// thus the first element is kept
return arr.filter((a, i) => !arr.some((b, j) => i > j && isEqual(a, b)))
}
console.log(customUnique(coords, (a, b) => a.x === b.x && a.y === b.y))
You can use originalArray.reduce() with an array instead of an object, so you can make use of array.find.
const coords = [{x: 260, y: 60}, {x: 180, y: 0}, {x: 180, y: 240}, {x: 360, y: 120}, {x: 180, y: 60}, {x: 180, y: 60}, {x: 180, y: 60}]
console.log(
coords.reduce((arr, e) => {
if (!arr.find(item => item.x == e.x && item.y == e.y)) {
arr.push(e);
}
return arr;
}, [])
);
Yet another simple solution using a temporary array. However not the best as I could say:
const filteredCoords: any = [];
for(let coord of coords)
if (!filteredCoords.find((ele: { x: number; y: number; }) => ele.x == coord.x && ele.y == coord.y)){
filteredCoords.push(coord)
}
I have to add gradient inside a foot shape according to the value of a point inside the foot. I have X and Y coordinates of a point and a value is attached to it. According to the value I have to assign color gradient like in the picture below. Higher the value of a point, darker the area is
So far, I have created the foot and added 2 color gradient to the whole foot, but I am unable to add gradient like this in the picture. Below is what I have achieved. Please if anyone could help me to find any solution to this
Here is the Stackblitz Link
Sample data :
[
{sensor: 0, value: 7.4, x: 108, y: 406}
{sensor: 1, value: 8.1, x: 68, y: 412}
{sensor: 2, value: 3.6, x: 108, y: 346}
{sensor: 3, value: 4.5, x: 61, y: 350}
{sensor: 4, value: 0.5, x: 108, y: 280}
{sensor: 5, value: 1, x: 49, y: 288}
{sensor: 6, value: 1, x: 122, y: 200}
{sensor: 7, value: 0.5, x: 30, y: 218}
{sensor: 8, value: 3.3, x: 140, y: 109}
{sensor: 9, value: 3.4, x: 105, y: 114}
{sensor: 10, value: 2.7, x: 78, y: 119}
{sensor: 11, value: 2.3, x: 51, y: 124}
{sensor: 12, value: 1.6, x: 22, y: 136}
{sensor: 13, value: 3.5, x: 121, y: 41}
{sensor: 14, value: 1.2, x: 85, y: 45}
{sensor: 15, value: 1, x: 50, y: 59}
]
Here is a hit map with 'populated' data (based on average value of closest points):
Just add the mask of the foot contour...
const data = [
{sensor: 0, value: 7.4, x: 108, y: 406},
{sensor: 1, value: 8.1, x: 68, y: 412},
{sensor: 2, value: 3.6, x: 108, y: 346},
{sensor: 3, value: 4.5, x: 61, y: 350},
{sensor: 4, value: 0.5, x: 108, y: 280},
{sensor: 5, value: 1, x: 49, y: 288},
{sensor: 6, value: 1, x: 122, y: 200},
{sensor: 7, value: 0.5, x: 30, y: 218},
{sensor: 8, value: 3.3, x: 140, y: 109},
{sensor: 9, value: 3.4, x: 105, y: 114},
{sensor: 10, value: 2.7, x: 78, y: 119},
{sensor: 11, value: 2.3, x: 51, y: 124},
{sensor: 12, value: 1.6, x: 22, y: 136},
{sensor: 13, value: 3.5, x: 121, y: 41},
{sensor: 14, value: 1.2, x: 85, y: 45},
{sensor: 15, value: 1, x: 50, y: 59},
];
const populateData = (points, width, height, step) => {
const populated = [];
for (let x = 0; x < width; x += step)
for (let y = 0; y < height; y += step) {
const distances = points.map(p =>
({...p, distance: Math.hypot(p.x - x, p.y - y)})).filter(d => d.distance < 100);
const sum = distances.reduce((s, d) => s + 1 / d.distance, 0);
const value = distances.reduce((a, d) => a + 1 / sum / d.distance * d.value, 0);
populated.push({x, y, value});
}
return populated;
};
const pd = populateData(data, 300, 500, 10);
const RECT_SIZE = 20;
const getColor = v => `rgb(255,${255 - v * 25},0)`
const svg = d3.select('svg');
pd.forEach(d => {
svg.append('rect')
.attr('x', d.x - RECT_SIZE / 2)
.attr('y', d.y - RECT_SIZE / 2)
.attr('width', RECT_SIZE / 2)
.attr('height', RECT_SIZE / 2)
.style('fill', getColor(d.value));
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="300" height="500" />
Here is a simple plot with the data you provided:
If you have more points, it can be a more precise picture
const data = [
{sensor: 0, value: 7.4, x: 108, y: 406},
{sensor: 1, value: 8.1, x: 68, y: 412},
{sensor: 2, value: 3.6, x: 108, y: 346},
{sensor: 3, value: 4.5, x: 61, y: 350},
{sensor: 4, value: 0.5, x: 108, y: 280},
{sensor: 5, value: 1, x: 49, y: 288},
{sensor: 6, value: 1, x: 122, y: 200},
{sensor: 7, value: 0.5, x: 30, y: 218},
{sensor: 8, value: 3.3, x: 140, y: 109},
{sensor: 9, value: 3.4, x: 105, y: 114},
{sensor: 10, value: 2.7, x: 78, y: 119},
{sensor: 11, value: 2.3, x: 51, y: 124},
{sensor: 12, value: 1.6, x: 22, y: 136},
{sensor: 13, value: 3.5, x: 121, y: 41},
{sensor: 14, value: 1.2, x: 85, y: 45},
{sensor: 15, value: 1, x: 50, y: 59},
];
const RECT_SIZE = 20;
const getColor = v => `rgb(255,${255 - v * 25},0)`
const svg = d3.select('svg');
data.forEach(d => {
svg.append('rect')
.attr('x', d.x - RECT_SIZE / 2)
.attr('y', d.y - RECT_SIZE / 2)
.attr('width', RECT_SIZE / 2)
.attr('height', RECT_SIZE / 2)
.style('fill', getColor(d.value));
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="300" height="500" />
I need to know the best method to check if the value is in the array before push it
I have an array :
coordinates: [
{x: 160, y: 160},
{x: 192, y: 160},
{x: 224, y: 160},
{x: 224, y: 192},
];
For each call of my function , I need to check if new coordinates is it before proceed to push.
const payload= {x: 224, y: 190}
//Next function call
const payload = {x: 224, y: 190} // need to refuse pushing this value
I tried filter and other JS methods without success.
for example:
coordinates.filter(c => {if(payload !== c){coordinates.push(new)});
This one doesn't work for me .
since each coordinate is an object, you'll need to do a deep comparison to check if the object exists in your array already:
const coordinates = [{
x: 160,
y: 160
}, {
x: 192,
y: 160
}, {
x: 224,
y: 160
}, {
x: 224,
y: 192
}];
const isInArray = newCoordinate => coordinates.filter(c => newCoordinate.x === c.x && newCoordinate.y === c.y).length > 0;
console.log(isInArray({
x: 0,
y: 0
})) // false
console.log(isInArray({
x: 160,
y: 160
})) // true
I hope this helps
var coordinates= [
{x: 160, y: 160},
{x: 192, y: 160},
{x: 224, y: 160},
{x: 224, y: 192},
];
const payload = {x: 225, y: 193};
for(let prop of coordinates){
if(prop.x == payload.x || prop.y == payload.y){
var includes = true;
} else {
includes = false;
}
}
if(includes == false){
coordinates.push(payload);
}
console.log(coordinates);
A simple checker function to check duplicate objects
var coordinates=[
{x: 160, y: 160},
{x: 192, y: 160},
{x: 224, y: 160},
{x: 224, y: 192},
];
const pushCoordinate=(obj)=>{
var flag=0;
coordinates.forEach((elem)=>{
if(obj.x===elem.x && obj.y===elem.y){
flag=1;
}
});
if(flag===1){
return false;
}else{
return true;
}
};
var payload1 = {x: 224, y: 190};
var payload2 = {x:224, y:190};
if(pushCoordinate(payload1)){
coordinates.push(payload1);
}
if(pushCoordinate(payload2)){
coordinates.push(payload2);
}
console.log(coordinates);
you can simply use filter array method to check x,y values
and if the filtered array has no length then there are no matching values and push payload object
let filteredArr;
let coordinates = [
{x: 160, y: 160},
{x: 192, y: 160},
{x: 224, y: 160},
{x: 224, y: 192}
];
// checker fn
const checker = (obj) => filteredArr = coordinates.filter(elm => obj.x == elm.x && obj.y == elm.y);
let payload = {x: 224, y: 190};
checker(payload);
// no matching
if (filteredArr.length === 0) coordinates.push(payload);
console.log(coordinates);
var payload = {x: 224, y: 190};
var coordinates = [
{x: 160, y: 160},
{x: 192, y: 160},
{x: 224, y: 160},
{x: 224, y: 192},
];
var filtered = coordinates.filter(c => c.x == payload.x &&
c.y == payload.y);
if (filtered.length == 0) filtered.push(payload)
console.log("Filtered:", filtered)
You can use some() to check whether coordinates array includes the values of payload object
const coordinates = [
{x: 160, y: 160},
{x: 192, y: 160},
{x: 224, y: 160},
{x: 224, y: 192},
];
const payload = {x: 224, y: 192};
if(!coordinates.some(({x, y}) => x === payload.x && y === payload.y)) {
coordinates.push(payload);
}
console.log(coordinates);
I have a set of images. Each image is displaying multiple objects. I want to show a tooltip whenever I hover my mouse pointer over each object in the image. I have pixel coordinates, and width and height for each object in an image.
I know a couple of different ways to implement a tooltip for an element but don't know how to handle pixel dimensions inside an image with respect to the tooltip.
You could use image maps for this:
var elements = [
{ label: 'Yellow', x: 112, y: 23, w: 112, h: 89 },
{ label: 'Pink', x: 27, y: 119, w: 110, h: 195 },
{ label: 'Brown', x: 198, y: 124, w: 112, h: 90 }
];
var img = document.querySelector('img'),
map = document.createElement('map');
map.name = 'my-map';
img.setAttribute('usemap', '#' + map.name);
elements.forEach(function(el) {
var area = document.createElement('area');
area.title = el.label;
area.coords = [el.x, el.y, el.x + el.w, el.y + el.h].join(',');
map.appendChild(area);
});
document.body.appendChild(map);
<img src="https://image.shutterstock.com/image-photo/three-macaroons-sweet-desserts-isolated-260nw-351030134.jpg">
If you have multiple images, you could make it into a reusable function:
addImageMap(
document.getElementById('image-a'),
[
{ label: 'Yellow', x: 112, y: 23, w: 112, h: 89 },
{ label: 'Pink', x: 27, y: 119, w: 110, h: 195 },
{ label: 'Brown', x: 198, y: 124, w: 112, h: 90 }
]
);
addImageMap(
document.getElementById('image-b'),
[
{ label: 'Drink', x: 111, y: 90, w: 310, h: 450 },
{ label: 'Burger', x: 471, y: 100, w: 320, h: 450 },
{ label: 'Fries', x: 891, y: 52, w: 300, h: 450 }
]
);
// If you want responsive image maps (see plugin added in HTML)
imageMapResize();
function addImageMap(img, elements) {
var map = document.createElement('map');
map.name = 'my-map-' + getUniqueMapId();
img.setAttribute('usemap', '#' + map.name);
elements.forEach(function(el) {
var area = document.createElement('area');
area.title = el.label;
area.coords = [el.x, el.y, el.x + el.w, el.y + el.h].join(',');
map.appendChild(area);
});
document.body.appendChild(map);
}
function getUniqueMapId() {
window.uniqueMapId = (window.uniqueMapId || 0) + 1;
return window.uniqueMapId;
}
img { width: 200px; }
<!-- Docs: https://github.com/davidjbradshaw/image-map-resizer -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/image-map-resizer/1.0.10/js/imageMapResizer.min.js"></script>
<img id="image-a" src="https://image.shutterstock.com/image-photo/three-macaroons-sweet-desserts-isolated-260nw-351030134.jpg">
<img id="image-b" src="https://previews.123rf.com/images/ifh/ifh1512/ifh151200179/49541375-illustration-of-set-of-three-objects-such-as-hamburger-french-fries-and-coffee.jpg">