Sort X and Y co-ordinates using Ramda - javascript

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));

Related

how to deleted an item with the same `x` and `y` but different key and also adds all the `g` with the same 'x' and 'y'

I have an array of objects:
let input = [
{ key: 0, x: 0, y: 0, g: 1 },
{ key: 1, x: 0, y: 0, g: 2 },
{ key: 2, x: 2, y: 0, g: 3 },
{ key: 3, x: 0, y: 0, g: 3 },
{ key: 4, x: 2, y: 2, g: 1 },
{ key: 5, x: 2, y: 2, g: 2 },
];
I mean I want to remove duplicate objects with the same x and y, and convert All of them to one, and also I want to add all the g which has same x and y. and I would like to sort them with the new key value.
let result = [
{ key: 0, x: 0, y: 0, g: 6 },
{ key: 1, x: 2, y: 0, g: 3 },
{ key: 2, x: 0, y: 0, g: 3 },
];
is it possible to help me.
I try by myself to remove but it doesn't work properly
const set = new Set(json1.map((item) => JSON.stringify(item)));
const uniq = [...set].map((item) => JSON.parse(item));
console.log(uniq)
This can be achieved with a standard 'group-by', grouping by a composite key of x and y and summing g.
(Your stated expected output is not consistent with your description of your problem. And it is unclear if you want to retain the original keys or generate new ones)
let input = [
{ key: 0, x: 0, y: 0, g: 1 },
{ key: 1, x: 0, y: 0, g: 2 },
{ key: 2, x: 2, y: 0, g: 3 },
{ key: 3, x: 0, y: 0, g: 3 },
{ key: 4, x: 2, y: 2, g: 1 },
{ key: 5, x: 2, y: 2, g: 2 },
];
const result = Object.values(
input.reduce((a, { key, x, y, g }) => (((a[`x_${x}_y_${y}`] ??= { key, x, y, g: 0 }).g += g), a), {})
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Convert a string to number in an object in JavaScript

I have an array of objects like this
const ArrayOfObject = [
{x: "1622078100000", y: 1},
{x: "1622010000000", y: 1},
{x: "1622009940000", y: 6},
{x: "1622009880000", y: 4},
{x: "1622009820000", y: 2},
{x: "1622073600000", y: 1}
]
I want something like this
const ArrayOfObject = [
{x: 1622078100000, y: 1},
{x: 1622010000000, y: 1},
{x: 1622009940000, y: 6},
{x: 1622009880000, y: 4},
{x: 1622009820000, y: 2},
{x: 1622073600000, y: 1}
]
parse the x prop from string to number. How to accomplish this in Javascript ES6 or ES5?
There is no special function to do this. You literally have to map over them.
Better instead to leave them as is, and only do it when needed
const ArrayOfObject = [
{x: "1622078100000", y: 1},
{x: "1622010000000", y: 1},
{x: "1622009940000", y: 6},
{x: "1622009880000", y: 4},
{x: "1622009820000", y: 2},
{x: "1622073600000", y: 1}
]
const ArrayOfObjectUpdated = ArrayOfObject.map(item => ({...item, x: Number(item.x)}))
You can use the + unary operator to convert a string to a number, like so:
const newArr = [];
ArrayOfObject.forEach(obj => newArr.push({x: +obj.x, y: obj.y}));
see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unary_plus

How to make sort function dynamic

I have an array as follows:
var arr1 = [{x: 0, y: 0}, {x: 10, y: 10}, {x: 20, y: 20}, {x: 30, y: 30}, {x: 40, y: 40}]
arr1 represents the data in an infotable created by a user and I have sorted arr1 in ascending order of x using .sort.
arr1.sort(function(a, b){return a.x - b.x});
When the user changes the name of the values in the infotable (arr1) from x to z or creates a new infotable with different names, I have to modify my code to sort it again.
var arr1 = [{z: 0, y: 0}, {z: 10, y: 10}, {z: 20, y: 20}, {z: 30, y: 30}, {z: 40, y: 40}]
arr1.sort(function(a, b){return a.z - b.z});
Therefore, I want my sort function to be dynamic so that I do not have to change the code when the name of the values in the array is changed or when an infotable with new names is created. I hope I got my question across clearly, any help is greatly appreciated!
You could store the key to sort by in a variable and use that variable instead. Example:
var arr1 = [{z: 0, y: 0}, {z: 10, y: 10}, {z: 20, y: 20}, {z: 30, y: 30}, {z: 40, y: 40}]
let keyToSortBy = 'z'
arr1.sort(function(a, b){return a[keyToSortBy] - b[keyToSortBy]});
If you are a fan of lodash.
import _ from "lodash"
let key = 'z' // dynamic key
_.sortBy(arr1, key);
You need to figure out a way to dynamically tell your algorithm what's the field you need to sort by. One example would be including a property in each element with the name of the field to sort. Sample:
var arr1 = [{x: 0, y: 0, sort: 'x'}, {x: 10, y: 10, sort: 'x'}]
var arr1 = [{z: 0, y: 0, sort: 'z'}, {z: 10, y: 10, sort: 'z'}]
Then, your sort function would be the same:
var sortFunction = function(a, b){return a[a['sort']] - b[b['sort']]}
arr1.sort(sortFunction);
arr2.sort(sortFunction);
Your sample data doesn't show much difference with the value sorted by either key as the results are the same for either sort.
I changed your data slightly to show the differences using the FF console.log
The sort function could be condensed by calling a function instead of the inline defined logic.
`
Test Page
</style>
</head><body>
<script>
console.clear();
var arr1 = [{z: 0, y: 40}, {z: 10, y: 30}, {z: 20, y: 20}, {z: 30, y: 10}, {z: 40, y: 0}];
console.log('original');
console.log(arr1.toSource());
console.log();
let keyToSortBy = 'z'
arr1.sort(function(a, b){return a[keyToSortBy] - b[keyToSortBy]});
console.log('original sorted by ascending "z"');
console.log(arr1.toSource());
console.log();
keyToSortBy = 'y'
arr1.sort(function(a, b){return a[keyToSortBy] - b[keyToSortBy]});
console.log('original sorted by ascending "y"');
console.log(arr1.toSource());
console.log();
</script>
</body></html>
`
Make a function that returns a function:
var arr1 = [{z: 0, y: 0}, {z: 10, y: 10}, {z: 20, y: 20}, {z: 30, y: 30}, {z: 40, y: 40}]
const sortBy = (key) => (a, b) => a[key] - b[key];
arr1.sort(sortBy('z'));
console.log(arr1);
If you need, you may "encode" the key in the array as a property (not iteratable):
var arr1 = [{z: 0, y: 0}, {z: 10, y: 10}, {z: 20, y: 20}, {z: 30, y: 30}, {z: 40, y: 40}];
arr1.sortKey = 'z';
const sortBy = (key) => (a, b) => a[key] - b[key];
arr1.sort(sortBy(arr1.sortKey));
console.log(arr1);
And last, you may create your own sort function to ALL arrays in your program:
var arr1 = [{z: 0, y: 0}, {z: 10, y: 10}, {z: 20, y: 20}, {z: 30, y: 30}, {z: 40, y: 40}];
arr1.sortKey = 'z';
Array.prototype.mySort = function() {
this.sort((a, b) => a[this.sortKey] - b[this.sortKey]);
};
arr1.mySort();
console.log(arr1);
You can add a sortByKey to the Array prototype:
Array.prototype.sortByKey = function (key) {
return this.sort((a, b) => a[key] - b[key]);
};
const arr = [
{ x: 1, y: 100 },
{ x: 100, y: 5 },
{x: 3, y: 99 },
];
console.log(arr.sortByKey('x'));
console.log(arr.sortByKey('y'));
See the example below. Every time you make a change use xzSort.
function xzSort(array){
array.sort(function(a, b){
var A = 'x' in a ? 'x' : 'z';
var B = 'x' in b ? 'x' : 'z';
return a[A] - b[B];
});
return array;
}
var a = [{z:40, y:40}, {z:10, y:10}, {z:0, y:0}, {z:20, y:20}, {z:30, y:30}];
console.log(a); console.log(xzSort(a)); a[3] = {x:10, y:15}; console.log(xzSort(a));

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; }, [])
);

How to find by array of objects in Mongoose?

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');
}
} );

Categories