Why do multiple calls of Array.fill effect unreferenced arrays? [duplicate] - javascript

This question already has answers here:
Array.prototype.fill() different from fill as I go [duplicate]
(1 answer)
Unexpected behavior using Array Map on an Array Initialized with Array Fill [duplicate]
(1 answer)
Closed 2 years ago.
Playing around with different ways of instantiating Arrays with Javascript and I noticed some interesting behavior:
matrix = Array(3).fill(Array(3).fill(0))
Creates an NxN matrix of 0 values
[
[0,0,0],
[0,0,0],
[0,0,0]
]
I then tried changing the first row of the matrix to be all 1's:
matrix[0].fill(1)
Which for some reason turned ALL values in the matrix to 1's:
[
[1,1,1],
[1,1,1],
[1,1,1]
]
This behavior doesn't make sense to me. Shouldn't only the first row be affected by the final call to Array.fill? What's going on here?

Your code is equivalent to
let row = [0,0,0]
let matrix = [row, row, row];
row.fill(1);
because .fill(Array(3).fill(0)) calls Array(3).fill(0) once to get the fill value - if the fill argument were a callback, then it would call it for each item in matrix - but the fill argument is a value
In javascript, arrays are said to be a reference
var a = [1,2,3], b=a;
b[0] = 4
will result in both a and b referencing an array with values [4,2,3]
so, since each row is the same array, your result is as you've seen
try this instead
const matrix = Array.from({length:3}, () => Array(3).fill(0))
matrix[0].fill(1);
console.log(matrix);
The above is equivalent to
const matrix = [Array(3).fill(0), Array(3).fill(0), Array(3).fill(0)];
matrix[0].fill(1);
Now each entry in matrix is a different Array, not the same one each time

Related

Find adjacent tiles in a two-dimensional grid

I have a two-dimensional grid, in which all tiles are defined by two coordinates x and y. I'm storing the tiles in an array like this var tiles = [];. Each tile is an object with an x and y property:
Tile = {
x: ...,
y: ...
}
For drawing purposes (canvas) I want to find out which tiles are adjacent to each other. I could do that by looping through each element and check if it is adjacent. Since that would take n^n number of accesses I don't think this is the right way to do it. I think there would be a more efficient algorithm.
I also thought that maybe storing the data in a different way would help, but again, I wouldn't know how.
You have 2 ways to create a grid :
Using a 2 dimensional Array which must be the easier thing for a grid
Store adjacent Tile of a Tile in it with something like that :
var tile0 = {
x:0, y:1
}
var tile1 = {
x:1,y:1, tileLeft : tile0
}
It can be useful if you want to create Pentagonal or Hexagonal... grid, ofcourse create your grid automatically with a for loop.
EDIT
A two dimensional array is simply an Array of Array
var arr = new Array()
for(var i = 0 ; i < 10 ; i++){
arr[i] = new Array()
}
Now you can set value like in a grid, for example :
arr[0][2] = {x:2,y:2} //It's a bit useless since indexes can be use for x and y
In that case, i have 10 Array stored in one Array so :
arr[10][0]
Will return following error : Uncaught TypeError: Cannot set property '2' of undefined, because index of arr are only define between 0 and 9.
With your data construct I can't see a way to check for all adjacent tiles without accessing each tile.
The "tried and true" two dimensional grid data construct would be...a simple two dimensional array. Then you can access tiles directly by their coordinates.

functional loop given a number instead of an array [duplicate]

This question already has answers here:
Tersest way to create an array of integers from 1..20 in JavaScript
(16 answers)
Closed 6 years ago.
The community reviewed whether to reopen this question 2 months ago and left it closed:
Original close reason(s) were not resolved
Say I have a number 18, instead of an array, in hand.
What is the best way to create a functional loop in JS given a number X instead of array of X elements?
I can do this:
[1,2,3].forEach(function(){
));
but if I have the number 3
I can do
for(var i = 0; i < 3; i++){
}
but I want that loop to be functional instead
If you have a number and you want to create a loop then you can use the number in limiter condition in the for loop.
for(var i = 0; i < number; i++)
Edit 1: you can use foreach on arrays only, in that case since you have a number already you can create a array of that length and then use the foreach on it.
var foo = new Array(number).fill(0);
foo.foreach()
Also another option is
var N = 18;
Array.apply(null, {length: N}).map(Number.call, Number)
result [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]
Many more options available in this thread Create a JavaScript array containing 1...N
I don't understand why you want to do this. An equivalent to:
[1,2,3].forEach(function(){ ... ));
Is
var limit = n;
while (--limit) {( // Note: 0 is falsy
function(){ ... }
)(limit);}
Or if you really want to use an array structure, the following will do:
new Array(limit).fill(0).forEach(function(){...});
You might be interested in Myth of the Day: Functional Programmers Don't Use Loops.
Per this question, you can "functionally" iterate over a linear sequence relatively easily using:
Array.apply(null, Array(number)).map(function () {}).forEach(...)
Not sure what advantage this gives you versus a regular for-loop with an index, though it is a neat trick.

How to choose pseudo-random values in an array javascript [duplicate]

This question already has answers here:
Generate unique number within range (0 - X), keeping a history to prevent duplicates
(4 answers)
Closed 7 years ago.
I know how to sort through an array like this
var rand = myArray[Math.floor(Math.random() * myArray.length)];
but what I am trying to do is use this in a loop to pick values from my array that I haven't picked with this function before.
In other words, let's say my array contains apples, bananas, and oranges. i want to be able to pick all three of those out randomly, but I don't want to pick able to pick out the same one more than once.(I hope this made sense)
You can remove the item from the array, so it will not be selected again
var rand = myArray.length ? myArray.splice(Math.floor(Math.random() * myArray.length), 1)[0] : undefined;
Demo: Fiddle
Note: It will modify the original array, so if you want to keep the original array as it was you need to keep a different copy

calculation on each array member

Given an array of arrays representing points, I want to find the minimum distance between points and return that distance and that starting point. I am using lodash and would like to be as functional as possible.
I have an array of arrays:
var all = [[1,2], [3,4], [4,5]];
I also have an object which has the current minimum distance and current array:
var cur_min = {'current_min': 10, 'point': [9,10]};
I want to find the minimum distance between all of the points in my array and if that distance is less than the current_min in my cur_min variable it will be updated. I have come up with the following:
function find_new_min(current, arr) {
return _.transform(arr, function(result, a) {
_.forEach(arr, function(b) {
if (!_.isEqual(a,b)) {
var d = get_distance(a,b);
if (d<result.current_min) {
result.current_min = d;
result.point = a;
}
}
});
}, _.clone(current));
}
I am expecting 6 different pairs of arrays since getting the distance between a point and itself is 0.
I cannot imagine looping over the same array twice is an efficient way to solve this problem. I've tried to rewrite this function using various lodash functions like _.forEach and _.reduce but I cannot find a way to not loop twice over the same array. Is there a faster way to solve this problem?
an example output for the above code is:
{ current_min: 1.222450611061632, loc: [ 1, 2 ] }
Your problem is one of the oldest: how to most efficiently sort an array of values based on some functional key. However, you also want to record the shortest distance and for that you need to compare to each and every other value. Because of this, you can't efficiently sort, you need to run over the entire array array.length times.
Considering you're expecting only six pairs of points, this seems like a severe case of premature optimization.
Readability-wise, unfortunately lodash doesn't offer functionality to produce a Cartesian product which you could then _.sortBy, nor does it offer a sort function that allows you to compare manually left and right and modify the values. I think your current implementation currently is as good as it gets with lodash.

How to find difference between two values? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I want return the difference between 2 values how to do that?
0.0.0.1.0 and 0.0.0.1.12
so the difference between these two values is 12
so how to calculate that I tried with Math.abs() but it is fine with single digits.
Assuming that they are strings (since you can't have more than 1 full stop in a valid JS number), you could split it by . character and calculate the difference of individual components:
function numStringDiff(a, b) {
// split them on dot characters
const aParts = a.split('.');
const bParts = b.split('.');
// loop using longest array length as a container for mapped results
return Array(Math.max(aParts.length, bParts.length)).fill(undefined).map((_, i) => {
const i1 = parseInt(aParts[i] || 0); // fetch aParts[i] or default to 0
const i2 = parseInt(bParts[i] || 0); // fetch bParts[i] or default to 0
// return compared value after defaulting the values.
return i2 - i1;
});
}
console.log(numStringDiff('0.0.0.1.0', '0.0.0.1.12'));
The problem here is that, as you stated in the comments, they can be of different length. To make it work in this scenario, we must iterate an amount of times equal to the length of the longest array and ensure that any missing items in the shorter one are defaulted to some non-breaking value like 0 so that we can safely subtract every digit present in the longest list with something or 0.
Note that 0 is a value I only used to ensure you can calculate a difference between different-length arrays, choose any (numeric or float) value that fits your needs.
If in this case the second argument has less dots than the first, negative difference will be returned, otherwise if first is longer than last, positive difference will be returned.
Some examples:
numStringDiff('1.1.1', '1.1') // => [0, 0, -1]
numStringDiff('1.1', '1.1.1') // => [0, 0, 1]
numStringDiff('1.1.1', '1.1.1') // => [0, 0, 0]
For the absolute distance between two values, one can simply .map over this array:
numStringDiff('1.1.1', '1.1').map(num => Math.abs(num));
// OR, using short form:
numStringDiff('1.1.1', '1.1').map(Math.abs);
And finally, should you need the result as a string, simply .join it back together with '.':
numStringDiff('1.1.1', '1.1').map(Math.abs).join('.');
Do know what you are trying to achieve though. If you're trying to manually bisect version numbers (like semver versions) I'd recommend against it since there will always be scenario's uncovered by this function such as pre-releases that wouldn't include only digits but rather 0.0.0-pre-foo-version or something. Since I don't know what it is you're trying to do exactly I'll leave that a responsibility for you to figure out :)

Categories