How to find by array of objects in Mongoose? - javascript

I have Mongoose.Schema like this:
const pixelSchema = mongoose.Schema({
x: String,
y: String,
color: String,
});
Also I have array of objects like this:
let pixels = [
{x: 0, 1: 0, color: 'blue'},
{x: 0, y: 1, color: 'blue'},
{x: 0, y: 2, color: 'blue'},
]
How can I check is one of this elements is already exist in database?
My solution now looks like this, but I think it's very inefficient.
pixels.map(pixel => {
Pixel.find(pixel, (err, pixels) => {
if (pixels) {
console.log('Find!');
}
});
});

Use that array as part of the $or query document. The $or operator lets you perform a logical OR operation on an array of two or more expressions and selects the documents that satisfy at least one of the expressions.
So your query in the end should just be:
let pixels = [
{x: 0, y: 0, color: 'blue'},
{x: 0, y: 1, color: 'blue'},
{x: 0, y: 2, color: 'blue'},
];
let query = { "$or": pixels };
Pixel.find(query, (err, pixels) => {
if (pixels) {
console.log('Find!');
}
});

You can try like
let pixels = [
{x: 0, 1: 0, color: 'blue'},
{x: 0, y: 1, color: 'blue'},
{x: 0, y: 2, color: 'blue'}
]
Pixel.find({ "$or": pixels}, function(error, pixel) {
if(pixel) {
console.log('Found pixel');
}
} );

Related

How do i access a property on the objects in an array and compare it?

So, I have a array with multiple objects with multiple properties:
let myArr = [{
id: 1,
x: 120,
y: 150,
}, {
id: 2,
x: 170,
y: 420,
}, {
id: 3,
x: 160,
y: 220,
}, {
id: 4,
x: 140,
y: 170,
}];
Now I want to see if the property of one of the objects in my array matches a variable.
But I dont know how to do that!
I want to check if the value of property "id" in one of my objects matches my variable.
Something like this:
if(myArr[0].id == myVar){
//do something
}
but this for each object in my array
Try like this
let myArr = [{
id: 1,
x: 120,
y: 150,
}, {
id: 2,
x: 170,
y: 420,
}, {
id: 3,
x: 160,
y: 220,
}, {
id: 4,
x: 140,
y: 170,
}];
let myVar = 1;
const found = myArr.find(element => element.id === myVar);
console.log(found)

Most time efficient route

I am looking for an algorithm to make a pathfinding tool. I believe, it is not exact salesman problem due to different nature of desired result.
Main goal is to build route through multiple points to visit more points in less time. It does not require to include all points into route, just opposite: if visiting a point or a group of points makes big detour, it is not worth including into route, as point/distance ratio would drop significantly.
Conditions:
there will always be starting point A (chosen by user), but finish can be back in point A, can be in point B or can be undefined to end route when visiting any more points would decrease efficiency
total pool of points (chosen by user) ranges from tens to thousands depending on filter
points can have weights to define how much visiting them contributes
app has to be more or less real time: user needs to get result within few minutes from entering starting conditions
To decrease waiting times I can make two optimizations: merge nearby points by distance into one point with increased weight and limit visitable points by certain radius from A or AB vector.
Bruteforce method does not work with big numbers, and popular pathfinding algorithm A* does not seem to be applicable here as well from what I understood. I thought about using ant algorithm or looking into other genetic algorithms, but is there any existing algorithm/method specifically made for such task? Also what (if any) further optimizations could be made to the pool of points for better results?
My approach so far (JavaScript). Scenarios 2 and 3 include distance to finish point as well.
let maxRatio = 0
let bestRoute = []
for (let path of allPaths) {
let distance = 0
let weight = 0
let currentPosition = {x: 0, y: 0}
for (let point of path) {
distance += getDistance(currentPosition, point)
weight += point.weight
currentPosition.x = point.x
currentPosition.y = point.y
}
if (weight / distance > maxRatio) {
maxRatio = weight / distance
bestRoute = path
}
}
With 2 sets of starting conditions (difference only in last point)
// input 1
[
{x: 10, y: 12, weight: 1.2},
{x: 15, y: 14, weight: 1},
{x: 6, y: 8, weight: 1},
{x: 30, y: 30, weight: 2},
]
// input 2
[
{x: 10, y: 12, weight: 1.2},
{x: 15, y: 14, weight: 1},
{x: 6, y: 8, weight: 1},
{x: 30, y: 30, weight: 4},
]
Scenario 1, from point A (0:0) to the end of route:
// output 1.1
Best weight/distance ratio: 0.15207666105559417
at visiting order [
{ x: 0, y: 0 },
{ x: 6, y: 8, weight: 1 },
{ x: 10, y: 12, weight: 1.2 },
{ x: 15, y: 14, weight: 1 }
]
Here we can see that one point, 30:30 with weight 2, is not included into the best route because it is simply too far away.
// output 1.2
Best weight/distance ratio: 0.16754421339617698
at visiting order [
{ x: 0, y: 0 },
{ x: 6, y: 8, weight: 1 },
{ x: 10, y: 12, weight: 1.2 },
{ x: 15, y: 14, weight: 1 },
{ x: 30, y: 30, weight: 4 }
]
Here we can see that point, 30:30 with weight 4 now, being included into the best route because visiting it benefits us.
Scenario 2, from point A (0:0) back to point A (0:0):
// output 2.1
Best weight/distance ratio: 0.07699655016791247
at visiting order [
{ x: 0, y: 0 },
{ x: 15, y: 14, weight: 1 },
{ x: 10, y: 12, weight: 1.2 },
{ x: 6, y: 8, weight: 1 },
{ x: 0, y: 0 }
]
Different order or points this time, but still furthest point not included
// output 2.2
Best weight/distance ratio: 0.08469183439702697
at visiting order [
{ x: 0, y: 0 },
{ x: 15, y: 14, weight: 1 },
{ x: 30, y: 30, weight: 4 },
{ x: 10, y: 12, weight: 1.2 },
{ x: 6, y: 8, weight: 1 },
{ x: 0, y: 0 }
]
And here, with weight 4, we include it.
Scenario 3, from point A (0:0) to point B (10:10):
// output 3.1
Best weight/distance ratio: 0.12459750581354255
at visiting order [
{ x: 0, y: 0 },
{ x: 6, y: 8, weight: 1 },
{ x: 10, y: 12, weight: 1.2 },
{ x: 10, y: 10 }
]
Here optimal route became shorter
// output 3.2
Best weight/distance ratio: 0.12459750581354255
at visiting order [
{ x: 0, y: 0 },
{ x: 6, y: 8, weight: 1 },
{ x: 10, y: 12, weight: 1.2 },
{ x: 10, y: 10 }
]
But even with weight 4 on (30:30) point we do not include it.

Merge arrays of X number of arrays of objects with single common key in ES6

So I have multiple objects in array that follow patter similar to the following.
Length of all arrays of objects is always the same. yX(there can be even like 100 yX(es) and also like 100s of x-y pairs in each array of objects. yX is different but always starting at 0 and is incremented by 1 (y0, y1, y2, y3, y4, ...).
const data = [
[{x: 0, y0: 1}, {x: 1, y0: 2}, {x: 2, y0: 3}],
[{x: 0, y1: 2}, {x: 1, y1: 3}, {x: 2, y1: 5}],
[{x: 0, y2: 1}, {x: 1, y2: 2}, {x: 2, y2: 3}]
]
How to merge them easily so I can get result like this?
const newData = [
{x: 0, y0: 1, y1: 2, y0: 1},
{x: 1, y0: 2, y1: 3, y2: 2},
{x: 2: y0: 3, y1: 5, y2: 3}
]
There is probably some simple solution to this that I can't find, but I got lost on this with all different combinations of forEach, .map, Object.assign(), etc.
You could merge the arrays and get all properties of the same index.
const
data = [
[{ x: 0, y0: 1 }, { x: 1, y0: 2 }, { x: 2, y0: 3 }],
[{ x: 0, y1: 2 }, { x: 1, y1: 3 }, { x: 2, y1: 5 }],
[{ x: 0, y2: 1 }, { x: 1, y2: 2 }, { x: 2, y2: 3 }]
],
result = data.reduce((r, a) => a.map((o, i) => ({ ...r[i], ...o })), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sort X and Y co-ordinates using Ramda

I have an array of the form:
[
{ i: 'text', layout: {x: 1, y: 0} }
{ i: 'text', layout: {x: 0, y: 0} }
{ i: 'text', layout: {x: 1, y: 1} }
]
I would like to sort the array using ramda package
I have reached so far as to sorting Y first --
const sortedY = R.sortBy(R.path(['layout', 'y']));
const temp = sortedY(originalContent);
Please suggest how I can sort x and y -
{x: 0, y: 0}
{x: 1, y: 0}
{x: 1, y: 1}
Use sortWith to sort using multiple comparators.
const xySort = R.sortWith([
R.ascend(R.path(['layout','x'])),
R.ascend(R.path(['layout','y']))
])
Looks like you want to use sortWith.
Here is an example:
var list = [
{ i: 'first', layout: {x: 1, y: 1} },
{ i: 'second', layout: {x: 1, y: 0} },
{ i: 'third', layout: {x: 0, y: 1} },
];
var xySort = R.sortWith([
R.ascend(R.path(['layout', 'x'])),
R.ascend(R.path(['layout', 'y'])),
]);
console.log(xySort(list));

How to get an array of the values of all properties of objects inside an array of objects?

I want to get an array of the values of each object I have.
I have this:
const numDataPoints = [
{
x0: {x: 807, y: 625},
x1: {x: 15, y: 20},
x2: {x: 5, y: 20}
},
{
x0: {x: 11, y: 6},
x1: {x: 16, y: 21},
x2: {x: 7, y: 22}
}
];
I want this:
[
[807, 625],
[15, 20],
[5, 20],
[11, 6],
[16, 21],
[7, 22]
]
I tried this:
numDataPoints.map((array) => array.map(axis => [axis.x, axis.y]));
but it throws this error:
Uncaught TypeError: array.map is not a function
You can use map method with Object.values and spread syntax ....
const data = [{ x0: {x: 807, y: 625}, x1: {x: 15, y: 20}, x2: {x: 5, y: 20} }, { x0: {x: 11, y: 6}, x1: {x: 16, y: 21}, x2: {x:7, y: 22} }];
const result = [].concat(...data.map(Object.values)).map(Object.values)
console.log(result)
You can use Array.map to transform each object into an array of two-element arrays and then reduce to flatten the result:
const numDataPoints = [{ x0: {x: 807, y: 625}, x1: {x: 15, y: 20},
x2: {x: 5, y: 20} }, { x0: {x: 11, y: 6}, x1: {x: 16, y: 21}, x2: {x:7, y: 22} }];
let result = numDataPoints.map(
item => Object.values(item).map(({x, y})=> [x, y]))
.reduce((arr, current) => [...arr, ...current], []);
console.log(result);
Use reduce for that - below will work for other data too as we don't hardcode any key's names here.
const res = numDataPoints.reduce((a, b) => a.concat(Object.keys(b).map(e => Object.values(b[e]))), []);
console.log(res);
<script>
const numDataPoints = [
{
x0: {
x: 807,
y: 625
},
x1: {
x: 15,
y: 20
},
x2: {
x: 5,
y: 20
}
}, {
x0: {
x: 11,
y: 6
},
x1: {
x: 16,
y: 21
},
x2: {
x: 7,
y: 22
}
}
];
</script>
You don’t have arrays in your numDataPoints array, but regular objects, so you can’t use map.
What you need is Object.values. Alternatively, to guarantee the same order of the keys x0, x1 and x2, destructure with {x0, x1, x2} and then use [x0, x1, x2].
The structure of numDataPoints suggests, that you actually want an array of two arrays, each with three [x, y] points, rather than just six [x, y] points. If you still want to flatten these sub-arrays, use concat or flatMap (currently a Stage 3 candidate, likely to become part of the ECMAScript edition finalized in June 2019).
Here are all six possibilities:
const numDataPoints = [
{
x0: {x: 807, y: 625},
x1: {x: 15, y: 20},
x2: {x: 5, y: 20}
},
{
x0: {x: 11, y: 6},
x1: {x: 16, y: 21},
x2: {x: 7, y: 22}
}
];
// Object.values, same structure
console.log(numDataPoints.map((obj) => Object.values(obj).map(({x, y}) => [x, y])));
// Object.values, flattened with concat
console.log([].concat(...numDataPoints.map((obj) => Object.values(obj).map(({x, y}) => [x, y]))));
// Object.values, flattened with flatMap
console.log(numDataPoints.flatMap((obj) => Object.values(obj).map(({x, y}) => [x, y])));
// Destructuring, same structure
console.log(numDataPoints.map(({x0, x1, x2}) => [x0, x1, x2].map(({x, y}) => [x, y])));
// Destructuring, flattened with concat
console.log([].concat(...numDataPoints.map(({x0, x1, x2}) => [x0, x1, x2].map(({x, y}) => [x, y]))));
// Destructuring, flattened with flatMap
console.log(numDataPoints.flatMap(({x0, x1, x2}) => [x0, x1, x2].map(({x, y}) => [x, y])));
You can use Object.keys to iterate over the keys within the object, like so:
let data = [{
x0: {
x: 807,
y: 625
},
x1: {
x: 15,
y: 20
},
x2: {
x: 5,
y: 20
}
}, {
x0: {
x: 11,
y: 6
},
x1: {
x: 16,
y: 21
},
x2: {
x: 7,
y: 22
}
}];
let result = data.map(obj => Object.keys(obj).map((key) => [obj[key].x, obj[key].y]));
console.log(result);
You may want to flatten the result, I'm not sure.
This is because what you get is an object, not an array. Although you could try (Es6) :
numDataPoints
.map(_ => {
return Object.values(_)
.map(({x, y}) => [x, y]);
}).reduce((acc, elem) => [...acc, ...elem], []);
The problem is that array is an object, so you have to map the keys before using another forEach.
const numDataPoints = [{ x0: {x: 807, y: 625}, x1: {x: 15, y: 20},x2: {x: 5, y: 20} }, { x0: {x: 11, y: 6}, x1: {x: 16, y: 21}, x2: {x:7, y: 22} }];
var foo = []
numDataPoints.forEach((points) =>
Object.keys(points).forEach(point =>
foo.push( [points[point].x, points[point].y] )
)
);
console.log(foo)
Here are a few different ways to get two different results (original nesting structure or flat structure) - also notice the sorting which could be a use-case for you - dictionary keys are sorted in the way they are declared (not alphanumerically):
const numDataPoints = [{ x0: {x: 807, y: 625}, x1: {x: 15, y: 20},
x2: {x: 5, y: 20} }, { x0: {x: 11, y: 6}, x1: {x: 16, y: 21}, x2: {x:7, y: 22} }];
// In case you need them sorted and in the original nesting:
console.log(
numDataPoints
.map(d => Object.keys(d).sort().map(k => [d[k].x, d[k].y]))
);
// In case you need them sorted and flattened:
console.log(
numDataPoints
.map(d => Object.keys(d).sort().map(k => [d[k].x, d[k].y]))
.reduce((a,v) => { v.forEach(value => a.push(value)); return a; }, [])
);
// In case you don't need them sorted and in the original nesting:
console.log(
numDataPoints
.map(d => Object.keys(d).map(k => [d[k].x, d[k].y]))
);
// In case you don't need them sorted and flattened:
console.log(
numDataPoints
.map(d => Object.keys(d).map(k => [d[k].x, d[k].y]))
.reduce((a,v) => { v.forEach(value => a.push(value)); return a; }, [])
);

Categories