Let's assume I have a function like this
function createMultiDimArray() {
let results = [];
let current = [];
for (let i = 1; i <= 10; i++) {
current.push(i);
if (i % 2 === 0) {
results.push(current);
current = [];
}
}
return results;
}
When I execute it
let arr = createMultiDimArray();
arr will look like this
[[1,2][3,4][5,6][7,8][9,10]]
I have tested it in multiple browsers and it seems to work. So apparently push() is creating a copy of the array passed to it instead of just using the reference, because otherwise arr would look like this (as current === [] when the function ends)
[[],[],[],[],[]]
I have searched the internet but I haven't found anything about this behavior of push(). So my question is: Is it safe to use push() to copy one array into another?
push does not copy the array (or whatever argument it's given).
Rather, the line
current = [];
creates a new array object and assigns it to the array reference current. From your analysis, I guess you assumed it would empty the existing array object referred to by current, but that's not the case.
No, in the code you are pushing the values into result using results.push(current);, and after that you create a new current array using current = [];. So after every even number you'll get sets of numbers pushed into results.
Related
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.
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.
I have an array of 11 objects which contain JSON data. I wrote a function in which a new key with a zero value is added to each of the objects. Now I want to update the value of the said key in all 11 objects. The data is stored in an array2 with 11 numbers. My for loop doesn't seem to work for this, and the only way to do it (so far) is to hard code it. Does anyone has a suggestion how this can be done?
The desired outcome would be this:
array[0].new_key = array2[0];
array[1].new_key = array2[1];
The first art of the function, before the for loop with j, is for adding the new key into the original array and that part works.
for (i = 0; i < array.length; i++) {
array.map(i => i.new_key = 0);
console.log(array)
for (j = 0; j < array2.length; j++) {
array[i].new_key = array2[j];
console.log(array)
}
}
}```
I split it into two functions, I realized that I made it too complicated and it didn't made sense. I wrote a second function that only updates all the key values, so indeed, I removed the inner loop as it was not needed. Thank you for the help.
.map() does not modify the original array:
The map() method creates a new array with the results of calling a
provided function on every element in the calling array.
You will want to get the result of the map by assigning it to a variable, and see what is happening there. Right now you don't do anything with it, so it will just disappear.
While the above is true for maps, in this case the original array is being modified as we access the object's properties and modify them there.
Suppose I have an array of objects called MyArray and that a certain function returns a reference for a particular element within that array; something like this:
MyArray = [Object1, Object2, ..., Objectn];
function DoWork() {
var TheObject = GetTheObject(SomeParamter);
}
At this point, TheObject points to a certain element in the array. Suppose I want to remove this element from MyArray, is this possible without having to reloop through the array to get the index of the element?
I'm looking for something like splice that would work with the reference to the element rather than the index of the element.
Simply use Array.prototype.indexOf:
let index = MyArray.indexOf(TheObject);
if(index !== -1) {
MyArray.splice(index, 1);
}
Keep in mind that if targeting IE < 9 you will need to introduce a polyfill for indexOf; you can find one in the MDN page.
I have the following javascript code:
var objectArray = [];
var allInputObjects = [];
var allSelectObjects = [];
var allTextAreaObjects = [];
//following returns 3 objects
allInputObjects = document.getElementById("divPage0").getElementsByTagName("INPUT");
//following returns 1 object
allSelectObjects = document.getElementById("divPage1").getElementsByTagName("SELECT");
//following returns 0 objects
allTextAreaObjects = document.getElementById("divPage2").getElementsByTagName("TEXTAREA");
//and following statement does not work
objectArray = allInputObjects.concat(allSelectObjects);
And my problem is that the last line is throwing an error.
I tried the above code in Firefox and it says allInputObjects.concat is not a function.
Any clues, I believe the script is not treating allInputObjects as an Array!
Any help will be appreciated.
getElementsByTagName returns a NodeList, which is similar to an Array except that it does not support all those prototype functions.
To seamlessly convert such an array-like object into an Array, use:
var arr = Array.prototype.slice.call(somenodelist, 0);
arr will almost be identical, except that it now has the Array prototype functions supported, like concat.
What the function actually does is returning a partial Array containing the elements of somenodelist, to be precise everything from index 0 and after. Obviously, this are just all elements, therefore this is a trick to convert array-like objects into real Arrays.
Why do you think that allSelectObjects is an array?
It is initially assigned to an empty array, sure. But then it's overwritten by the getElementsByTagName call on line 6(ish). Variables in Javascript are not strongly typed, so the initial assignment does not force later assignments to also be arrays.
I suspect you'll have some type of NodeList or similar, rather than an array, in the variable when you invoke the final line. (That's what's returned by the method in Firefox, at least.)
As Andezej has pointed out, you're not dealing with an array here, you're dealing with a kind of node list.
Here's one way you can create an array to work with based on the result of getElementsByTagName
var tags = obj.getElementsByTagName('input');
for (var j=0;j<tags.length;j++) {
resultArray.push(tags[j]);
}
Just another funny way to convert your NodeList to an array:
var tags = obj.getElementsByTagName('input'),
tags2Arr = (
function toArr(i){
return i ? toArr(i-1).concat(tags[i]) : [tags[0]];
}(tags.length-1)
);
Now if you add a method to the Array.prototype:
Array.prototype.clone = function() {
var arr = this;
return (function clone(i){
return i ? clone(i-1).concat(arr[i]) : [arr[0]];
})(this.length-1);
};
You can convert a NodeList to an array, using this oneliner:
Array.prototype.clone.call(obj.getElementsByTagName('input'));