Javascript array in array - first index is always overwritten - javascript

I have a problem with my JS function. For simplification, I want to fill an array (arr1) with n other arrays (arr2). In my loop I use a counter for the current postion in arr1 (cant use arr1.push for a reason). If I log all my arr2's in arr1 they are all the same, always the last one that was added. So I wrote a basic script to test it. I always log the first element and incement the counter.
I'm new to JS, is there some huge misunderstanding I don't get?
function test(){
var arr1 = [];
var arr2 = [];
var counter=1;
arr2[0]="first";
arr2[1]="first";
arr2[2]="first";
arr1[0]=arr2;
arr1[0].forEach(function(elem){console.log(elem);});
for (var i = 0; i < 10 ; i++) {
arr2[0]=counter;
arr2[1]=counter;
arr2[2]=counter;
arr1[counter]=arr2;
arr1[0].forEach(function(elem){console.log(elem);});
counter++;
}
}
<button onclick="test()">Click</button>

You can try to use the spread operator.
arr1[0]=[...arr2];
arr1[counter]=[...arr2];
An array is a reference type, so you always refer to the base, you don't put a copy of it inside of arr1 but a reference to the arr2.
You want a copy of arr2 to be assigned to arr1.
You can do this by creating a new Array, or more modern the ... spread operator

As Pointy said it, it just referenced the arr2 and doesn't create a copy.
So you need to
arr2=new Array();
at the beginning of the loop.

Related

Dynamic Array pushing Vs Assigning to a Static Size Array: Time Complexity in JavaScript

I have a dynamic array as shown below:
const array1 = [];
for(let i = 0; i < 5; i++)
array1.push(i+1);
and another array:
let Array2 = Array(6); //Note here the size is 6 as compared to the array1 which has initial size as 5.
for(let i = 0; i < 5; i++)
Array2[i] = i+1;
Now I want to append an element to the last of the array as shown below:
array1.push(6);
Will the above operation will be O(n) as this process will result in array1 to be moved to a new array and then appending 6 at the end or will it just be O(1).
Also which declaration is better?
const array1 = []
and then adding the elements to it, or initializing an empty array (whose size is known) and then substituting in the elements one by one.
So here's the example for the same:
It is known that first five elements are coming from a for loop (which invokes another function) and the last element is coming from a function getElement as shown below:
Method 1:
const Array1 = [];
for(let i = 0; i < 5; i++)
Array1.push(getFirstFiveElements(i));
//Where getFirstFiveElements is another function
Array1.push(gettheSixthElement());
or Method 2:
const Array2 = Array(6);
for(let i = 0; i < 5; i++)
Array2[i] = getFirstFiveElements(i);
Array2[Array2.length - 1] = gettheSixthElement();
It's always better to initialize an array whose size is known. Because when you push elements onto an array that lacks the number of empty slots needed, behind the scenes JavaScript has to copy the existing underlying array into a new array twice the size of the old array. Therefore adding values to the array is not O(1) on average because sometimes it results in the entire array being copied. Whereas if you initialize the array with a known size, all additions to the array are O(1).
Why do we need to initialize the length?
Theoretically there is no need for this. It can even result in confusing behavior, because all tests that use the length to find out whether an array is empty or not will report that the array is not empty.
Some tests show that setting the initial length of large arrays can be more efficient if the array is filled afterwards, but the performance gain (if any) seem to differ from browser to browser.

Assigning 'undefined' a value, how?

I was trying to assign a value to the items of an empty array, but I couldn't manage.
I used the Array constructor, and tried using both the .map() and the for ... of, but it didn't work.
let chrom = new Array(4);
const randomN = () => Math.floor(Math.random()*2);
for (g of chrom) {
g = randomN()
}
However, this solution worked
let emptyArr = new Array(4);
const randomN = () => Math.floor(Math.random()*2);
for (i=0; i<chrom.length; i++) {
chrom[i] = randomN()
}
Somehow it seems like only specifying the indexes does the trick.
does anybody know why this happens? what should I read? I tried looking in the documentation, but I couldn't see anything there.
The explanation is that in your first solution, g is going to be a local variable (a copy) instead of a reference to the actual value in the chrom array.
For example:
let nums = [1, 2, 3]
for (let num of nums) {
num = 1 // num in this case is a totally different variable
}
console.log(nums) // will still output [1, 2, 3]
Here is a good article explaining the difference between value vs reference in Javascript.
Using the for...of loop does not work since g is only a variable that holds the value of the element of the array at the current index; modifying it does not modify the array.
Array#map skips all empty slots, like those created by Array(size) or new Array(size). An array literal with an empty slot looks like this: [,]. You can fill the array before mapping or use spread syntax.
chrom.fill().map(randomN);
//or
[...chrom].map(randomN);
The standard index-based for loop uses the length of the array, which includes empty slots and sets elements using the index, so it has the desired effect.

How can I insert a value on every index of array using a loop and slice and/or concat?

I'm currently doing an assignment for school and could really use your help.
I have to declare a function which takes two arguments, x and an array, arr. It has to return an array which contains multiple arrays with x inserted into respectively index 0 in the first array, index 1 in the second array and so on until there's no more numbers in the array. See picture of an example and for clarification of what the final result is expected to look like. It has to work on any given array and the assignment specifies that slice() and concat() would be good to use. example of assignment
function insert_all_positions (x, arr) {
var newArr = [];
for(var i = 0; i < arr.length; i++) {
return(arr.concat(x)); }
};
This just adds the x-value to the end of the array and I have to loop it so the value will be inserted at all indexes. I'm thinking the array.splice() method can be used, I'm just not sure how as I'm not particularly experienced with it. Thank you :)
As Nina already said: the idea of assignments is, that you try something yourself which we can then help you to improve.
Nonetheless, here is one simple way of doing what was required:
function iap(v,arr){
var l=arr.length, ret=[];
for (var i=0;i<=l;i++) ret.push(arr.slice(0,i).concat([v],arr.slice(i,l)));
return ret;
}
console.log(iap(8,[1,2,3]));
Try this
function myFunc(x,arr){
let result =[]
for(let i=0;i<arr.length;i++){
let arrToAdd = [...arr]
arrToAdd[i]=x
result.push(arrToAdd)
}
return result
}
You create a result array that you push your arrays into, then you run a loop that will run the exact number of times as the length of your argument arr. Each iteration of the loop creates a new array that is a copy of arr and then you just change one number in it each time and add the entire array to the result.

JavaScript Copy Array By Value

I have created an array and received another from a php file.
The data is fine but when i try to copy one array to another, it seems like when i change arr1 then arr2 is also changed.
It is being copied "by reference" and not "by value" as i need
I also tried slice() butit doesn't work, The variable does not being copied at all, not even "by reference" in that way.
// arr1[0] = "Hey";//this array is coming from another file and the data is fine
var arr2 = [];
arr2[0] = arr1[0];
arr2[0] += "1"; // right now arr1 and arr2 both has "Hey1" in them.
Any ideas?
Thank You
An array is an object in Javascript. As you might know objects are copied by reference. You could take a look here: What is the most efficient way to deep clone an object in JavaScript?
You can do a deep, rather than a shallow, copy of an array of strings like this:
var arr2 = [], i = 0;
for (i = 0; i < arr1.length; i++) {
arr2[i] = String(arr1[i]);
}
EDITED: oops, swapped deep and shallow.

How do array sizes work in Javascript

In JavaScript, if you set an array to be of size 5 ( var foo = new Array(5); ), is this just an initial size? Can you expand the number of elements after it is created. Is it possible to do something like this as well - arr = new Array() and then just assign elements one by one? Thanks in advance :-)
Yes it is just an initial size, and it is not required. If you don't use a single number, you can immediately populate.
It is also more common to use the simpler [] syntax.
var arr = ['something', 34, 'hello'];
You can set (or replace) a specific index by using brackets:
arr[0] = "I'm here replacing whatever your first item was";
You can add to the end by using push:
arr.push('add me');
There may be faster performance in some browsers if you do it like this instead:
arr[arr.length] = 'add me';
You can add something at any index.
You can remove an item completely using splice:
arr.splice(0, 1); // remove first item in the array (start at index 0, with 1 being removed)
When you give a new array an explicit size in javascript (using new Array(5)), you populate each index with value of undefined. It is generally considered better practice to instantiate using the array literal [] expression:
var arr = [];
Then, you can push new elements using push()
var arr = [];
arr.push('first value'):
arr.push('second value'):
Check out the MDC Array documentation for more info: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array
Theres a few ways to declare and put values in an array.
First like what you want to do,
var myarr = new Array();
myarr[0] = 'element1';
myarr[1] = 'element2';
myarr[2] = 'element3';
Second way is to define them
var myarr =new Array("element1","element2","element3");
and third is similar to the second
var myarr =["element1","element2","element3"];
You can also check out https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array for a little more information about using the arrays as well. You could use push and pop if you wanted to as well.
If you use jquery or mootools they also have built-in functions to perform on arrays,
http://api.jquery.com/jQuery.each/ for instance.
Have a look at http://www.w3schools.com/js/js_obj_array.asp
var myCars=new Array(); // regular array (add an optional integer
myCars[0]="Saab"; // argument to control array's size)
myCars[1]="Volvo";
myCars[2]="BMW";
Check the documentation for Array, but the simple answer to your question is yes.
var arr5 = new Array(1, 2, 3, 4, 5); // an array with initial 5 elements
var arr = new Array(); // an array without initial
You can also use array literals:
var arr5 = [1, 2, 3, 4, 5];
var arr = [];
Arrays are dynamic in JavaScript. You don't have to initialize them with a certain length. In fact you should use the literal notation [] because of the Array constructor's ambiguity:
If you pass only one parameter to Array, it will set the array length to this parameter. If you pass more than one parameter, these elements are added to the array.
How is the size of the array determined?
The size of an array is the highest index + 1. This can be quite confusing. Consider this:
var arr = [];
arr[41] = 'The answer?';
console.log(arr); // [undefined, undefined, ..., 'The answer?']
console.log(arr.length) // 42
You can even set the length yourself by assigning a number to .length:
arr.length = 99;
If you now add a new element using arr.push(), it will get the index 100 and the length will increase. Whenever you add an element to the array via an index, it is tested whether arr.length is smaller than the index and updated accordingly. But it does not get smaller.
So in fact what var arr = new Array(5) is doing is setting the length of the array to 5. Nothing else.
For more information about creating and populating arrays, I suggest to read about it in the MDC JavaScript Guide.

Categories

Resources