Find unique node number given x and y coordinates - javascript

Referring to this picture, the first array is x-coordinate and second array is y-coordinate. The blue boxes will be the node number for each (x,y). if the point has been labelled before, it will remain with the same node number that was assigned to it previously. And if the point has not been labelled before and is new, it will be assigned a new node number :) For my attempt, I am trying to find the index of all mirror coordinates and the number of mirror coordinates present with the code below. However, I am unsure what the next step should be to get the value of the blue boxes in an array. This is in javascript. Any guidance will be appreaciated :)
for (let i=0;i<jaja+1;i++){
if ( (x_all[arr[m]+i]==x_all[arr[m]-i]) ){
}
}

This is a fairly straightforward 'zip' with an added map of previously seen points, here tracked in an object keyed by the JSON string of each point, and retrieving/setting the next id using logical nullish assignment (??=).
const xs = [102, 152, 202, 252, 202, 152, 302, 10, 332, 10, 1];
const ys = [100, 50, 60, 70, 60, 9, 3, 2, 1, 2, 100];
let seen = {}, count = 1;
const result = xs.map((x, i) => {
const point = { x, y: ys[i] };
const id = (seen[JSON.stringify(point)] ??= count++);
return { id, ...point };
})
console.log(result)
see more 'zip' discussion here: Javascript equivalent of Python's zip function

Related

Combining two arrays via the sum of two fields Javascript

Looking for general advice on approaches here. Description and pseudocode below:
Array1 has 100 objects type integer
Array2 has 100 objects type integer
Create Array 3 10,000 objects summing the two arrays
Array3.1 = Array1.[Field1] from 1 to 100 + Array2.1.[Field1]
Array3.2 = Array1.[Field1] from 1 to 100 + Array2.2.[Field1]
Array3.3 = Array1.[Field1] from 1 to 100 + Array2.3.[Field1]
……
Array3.100 = Array1.[Field1] from 1 to 100 + Array2.100.[Field1]
Challenges:
Not sure how to easily reference the field within an object in the array. I can pull up the object line but this returns the entire object whereas I only want to pull one field. This would be helpful beyond this particular question.
Not sure about the best method to create the new array, whether it should be a loop or something else.
Further background
The final objective will be to create an output that compares the sum of the specific field for every pair within the two arrays to find and then rank them from best to worst.
It's not that difficult.
Every entry in the resulting array is just the 2nd array with the value at the current index of the first array added to it.
const a1 = [0, 5, 10, 15, 20];
const a2 = [0, 2, 4, 6, 8];
const result = a1.map(x => a2.map(y => x + y));
console.log(result);
If you don't want the resulting array to nested, use flatMap:
const a1 = [0, 5, 10, 15, 20];
const a2 = [0, 2, 4, 6, 8];
const result = a1.flatMap(x => a2.map(y => x + y));
console.log(result);

How to print out filtered elements?

How do I print out the filtered elements from the array?
I tried console.log('randomNumbers/smallNumbers');
But they didn't work.
Please advise, much thanks!
const randomNumbers = [375, 200, 3.14, 7, 13, 852];
const smallNumbers = randomNumbers.filter(num => {
return num < 250;
});
It's not the logging you have troubles with - but Array.filter function. You seem to think it somehow consumes the whole array at once, hence attempt to use length and name the argument the same way as the original array.
What happens instead is that the function you pass in randomNumbers.filter (as its parameter) is called once per each element of that array, taking this element as its first argument.
If result of the function's call for this element is truthy, the element will stay in the result of .filter. If falsy, it gets discarded.
So it can written as simple as this:
const randomNumbers = [375, 200, 3.14, 7, 13, 852];
const smallNumbers = randomNumbers.filter(number => number < 250);
// log the resulting array
console.log(smallNumbers);
// log the small numbers' ratio
console.log((smallNumbers.length / randomNumbers.length).toFixed(2));
const randomNumbers = [375, 200, 3.14, 7, 13, 852];
const smallNumbers = randomNumbers.filter(number => number < 250);
// log the resulting array
console.log(smallNumbers);
// log the small numbers' ratio
console.log((smallNumbers.length / randomNumbers.length).toFixed(2));

Summing by index reference a group of arrays

I have a function that needs to take an array from each in a group of documents, and sum each position in each array with it's index 'partner' at the [n]th position.
The arrays look something like this......
[300, 230, 45, 0, 0, 0]
[200, 100, 0, 0, 0, 0]
[2, 1, 0, 0, 0, 0]
...
From which I would want to return [502, 331, 45, 0, 0, 0]. Using this question which is asking almost the same thing, I copied a reduce function, so my function now looks like this...
this.projects.forEach(function (project) {
let arrays = project.yearsTotal
result = arrays.reduce(function (r, a) {
a.forEach(function (b, i) {
r[i] = (r[i] || 0) + b;
});
return r
}, []);
})
However, this tells me that 'a.forEach is not a function', I must admit that I'm not sure exactly what the reduce function is doing, but I think perhaps that it isn't working because my arrays are not an array of arrays, they exist separately.
Javascript tells me they are objects, not arrays, but I'm not sure that is significant. Please could someone tell me how to do this?
The difference with the question you linked seems to be your numeric data, that is stored inside array of objects (in property yearsTotal) - and not in array of arrays of numbers.
If that's the case, you can just create another array storing only the values you need:
const projectYearsTotal = this.projects.map(p => p.yearsTotal);
... and then you can proceed with reduce-forEach-ing it.
Your current solution tries to 'zip-sum' the array of numbers (value of 'yearsTotal' of each individual project), not array of arrays of numbers. Hence forEach is not a function error.

Javasript array functions with no arguments [duplicate]

This question already has answers here:
Create an array with random values
(24 answers)
Closed 3 years ago.
This is more like a silly question but I have to ask it.
It is a good practice to call an array function like map without arguments?
Let's say I already have an array 'x' on my code with a specified length and I want to make another array with the same length but with different content.
For example:
function generateRandomContent() { ... }
const x = [1, 2, 3, 4, 5]
const y = x.map(() => generateRandomContent())
// or
const z = Array(x.length).fill().map(() => { ... })
Of course I could pass an argument and never use it, but it is there a good way and a bad way to do it?
You should not use .map here. A mapping operation is when you take some input and generate a new output. So you have a relation that looks like this x -> y for a single element, then you apply it to the entire array to generate a new array using the same mapping rule:
const input = [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100];
//mapping relationship
const toCharacter = x => String.fromCharCode(x);
const result = input.map(toCharacter);
console.log(result.join(''))
If you just want to create a new array based on the length of the original but with totally unrelated content, then you are better off to use Array.from which can create an array with a given size and takes a second argument that will fill it with content:
function generateRandomContent() {
return Math.floor(Math.random() * 100);
}
const x = [1, 2, 3, 4, 5]
const y = Array.from({length: x.length}, () => generateRandomContent());
//or just pass the function reference
const z = Array.from({length: x.length}, generateRandomContent);
console.log(y);
console.log(z);

Add two arrays of integers into an array of arrays so it creates coordinates pairs

I have two arrays, one with x coordinates and one with y coordinates. I need to create a new array of arrays that group the coordinates.
yCord = [30, 29, 31, 32];
xCord = [0, 1, 2 ,3];
Here is what I had.
var cordPairs = {};
xCord.forEach((key, i) => cordPairs[key] = yCord[i]);
But that pairs the values in an object, I need an array now.
{0: 30, 1: 29, 2: 31, 3: 32}
Desired result:
cordPairs = [[0, 30], [1, 29], [2, 31], [3, 32]]
You need the data in array format so this should work:
const yCord = [30, 29, 31, 32];
const xCord = [0, 1, 2 ,3];
const coords = xCord.map((el, index)=> [el, yCord[index]]);
console.log(coords);
You could take the x and y values in an array and transpose this array.
const
transpose = (r, a) => a.map((v, i) => [...(r[i] || []), v]),
yCord = [30, 29, 31, 32],
xCord = [0, 1, 2 ,3],
result = [xCord, yCord].reduce(transpose, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
The other answers are great - but...
This may actually be a situation where, instead of creating a method that can perform the process, you would actually want to create a new Constructor function that will return an object with the innate ability to iterate how you want.
function CoordinateArray(x, y) {
if (y.length != x.length) return Error("CoordinateArray: Incorrect Array Bounds");
let i = 0;
return {
y,
x,
[Symbol.iterator]: function*() {
while (i < this.y.length) {
yield [this.x[i], this.y[i]];
i++;
}
}
}
}
A functioning code example:
let yCord = [30, 29, 31, 32],
xCord = [0, 1, 2, 3];
function CoordinateArray(x, y) {
if (y.length != x.length) return Error("CoordinateArray: Incorrect Array Bounds");
let i = 0;
return {
x,
y,
length: x.length,
[Symbol.iterator]: function*() {
while (i < y.length) {
yield [this.x[i], this.y[i]];
i++;
}
}
};
}
let coords = new CoordinateArray(xCord, yCord);
console.log([...coords]);
Why would you do it this way?
When utilizing something in a coordinate system it's likely that the functionality of looping over coordinates is a commonality within your code. A.e. It happens more than once, and if it needs to be extended, the functionality may be needed again.
Creating a Constructor for this purpose allows you to create code that lends itself to higher clarity and concision.
It also allows for greater innate control over how you code.
What do I mean by that?
Creating a method/function that simply iterates over the two Arrays once and returns a bundled coordinate Array is well and good - but let's say that somewhere down the line you simply need to adjust all the x values. With a normal function you would either need to write conditions, or perform the function and, afterwards, perform additional work to get the results you want. A.e.:
getCoordinateArray(xCord, yCord) //perform a lot of work
.map(([x,y]) => [x*2,y]); //perform more work
Whereas if you provide yourself with a Constructor with innate iteration mechanics, you could save yourself the hassle while providing more iteration options:
let coords = CoordinateArray(xCord, yCord); //initial work
coords.x = coords.x.map(i=>i*2); //minimal work
It may not be plain to see, but by doing it the Constructor way, you're adjusting the Object as minimally as possible while still maintaining a functional paradigm. You don't worry about the total results, you only adjust what you need to and the outcome will be as expected. Furthermore, it's crystal clear what you're adjusting in the second example coords.x, whereas in the first it's more of a jumble.
To extend on this as well, you can also abstract away simple mechanics as the above to make your intentions even more clear. Simply add on a method to your Constructor:
function CoordinateArray(x, y) {
return {
...
//new method
move: function(s, c = s.split("")[0]) { this[c] = this[c].map(new Function(c,"return" + s)) },
...
}
}
And the above will become this instead:
let coords = new CoordinateArray(xCord, yCord); // initial work
coords.move("x*2"); // minimal, clear, work.
let yCord = [30, 29, 31, 32],
xCord = [0, 1, 2, 3];
function CoordinateArray(x, y) {
if (y.length != x.length) return Error("CoordinateArray: Incorrect Array Bounds");
let i = 0;
return {
x,
y,
move: function(s, [c,] = s.split("")) { this[c] = this[c].map(new Function(c,`return ${s};`)) },
length: x.length,
[Symbol.iterator]: function*() {
while (i < y.length) {
yield [this.x[i], this.y[i]];
i++;
}
}
};
}
let coords = new CoordinateArray(xCord, yCord);
coords.move("x*2");
console.log([...coords]);
Which, I think anyone will say, is much easier to read - but more importantly with that readability it isn't costing you anything. Even though there is no assignment to coords.x, it isn't mutating your data. Normally with operations you'll see things like x = x.map(); at each step, which does showcase immutability, but it's redundant and obfuscatory when it needn't be.
Yes, a simple function as provided by the other answers may be all you need - but if you are performing coordinate manipulation often in your code, I would urge you to consider alternative routes other than stacking multiple functions. A Constructor would allow you to keep what you need with the benefit of extreme clarity and flexibility with your data and methods, and minimal impact on Scope.
All this being said...
Your use case will decide the best option!
Again, the other answers are perfectly valid ( in fact, a few of the other people who answered I purposely follow because they are very knowledgeable and inspiring) - I only offer this answer to provide more insight into operating with things like coordinate systems. I've written many apps, components, etc, that have utilized them and I've put a lot of time into the process of making them clear and effective for myself as well as others!
Hope this helped! Happy Coding!
Iterate the index of the two arrays, Package the pairs in a javascript array and pus to make an structure of them:
yCord = [30, 29, 31, 32];
xCord = [0, 1, 2 ,3];
var cordPairs = [];
for(var i = 0; i < xCord.length; i++)
{
cordPairs.push([xCord[i], yCord[i]]);
}
Long story short, you want to zip those arrays. With libraries like lodash, it's as simple as
cordPairs = _.zip(xCord, yCord);

Categories