javascript splice - strange issue - javascript

I wonder what's wrong with this
$(function() {
var arr1=new Array('A','B','C','D','E','F','G');
var arr2=new Array('F','D','B');
var arr3=arr1;
for(x=0; x<arr3.length; x++) {
if(jQuery.inArray(arr3[x],arr2) == -1) {arr3.splice(x, 1);}
}
alert(arr1.join(','));
alert(arr3.join(','));
});
I thought arr1 should still be Array('A','B','C','D','E','F','G'), but after this operation, arr1 becomes arr3. It doesn't make sense to me since the entire operation doesn't touch arr1 at all.
Found the answer after posting this. See duplicating arrays javascript splicing

Assignment like var arr3=arr1; are done by reference i.e. arr3 variable now points to same location where arr1 variable points to. The underlined data (in this case array) is the same. Essentially arr1 and arr3 are same. So any change done via one is visible via other. If you want to duplicate the array of simple types use slice(0)
var arr3 = arr1.slice(0);

var x = [3, 4, 5]
var y = [3, 4, 5]
var z = y
x === y // false
y === z // true (y and z reference the same object)
y.push(6)
y // [3, 4, 5, 6]
z // [3, 4, 5, 6]
var x2 = x.slice(0)
x2 === x // false
x2.push('foo')
x2 // [3, 4, 5, 'foo']
x // [3, 4, 5]
Use Array.prototype.slice to copy an array.

arr1 is a Array Object. when you copy arr1 like var arr3 = arr1, we just get a new reference to the original object.
so , when you change the arr3 , arr1 also change.
you should search "how to clone a object", this may help you.

Related

array.includes doesn't work when checking if an iterator exists in array [duplicate]

This question already has answers here:
What is the difference between ( for... in ) and ( for... of ) statements?
(18 answers)
Closed 1 year ago.
I'm encountering some unexpected behavior in my JavaScript code which I'd like to understand. I want a one-line function to detect if a number exists inside an array of integers. The number being checked is the iterator of a loop in another array. I'm using the standard includes() function, should note the same happens with an indexOf() >= 0 check. For this test we have the following code:
const array1 = [0, 1, 2, 3];
const array2 = [1, 2];
for(let i in array1)
console.log(array2.includes(i));
To my surprise each output returns false instead of the expected false true true false sequence. How can this be? I know I'm checking i not arr[i], but i still corresponds to the numbers included in those arrays: 0 is still 0, 1 is still 1, etc. Using arr.includes(1) does return true, so why not arr.includes(i) when i is also 1?
A for...in loops through all the keys/properties.
It is a string, not number, which comes from the bracket property accessor
const array1 = [0, 1, 2, 3];
const array2 = [1, 2];
for(let i in array1)
console.log(typeof i, i, array2.includes(i));
A for...of loops through the values if the object is an iterable, defined by some function that I don't know off the top of my head and isn't important right now.
const array1 = [0, 1, 2, 3];
const array2 = [1, 2];
for(let i of array1)
console.log(typeof i, i, array2.includes(i));
Also know that your for...in loop doesn't do what you seem to expect it to do when array1 isn't an incrementing integer list starting at 0:
const array1 = [6, 4, 3, 95, 45, 3, 3];
for(let i in array1)
console.log(typeof i, i);
So what you should do is just use for...of (or Array.prototype.forEach, or a traditional for (let i = 0; i < arr.length; i++) loop, etc.) unless you need a for...in (which is almost never), or in this case I guess you can cast the string to a number before checking if it's called on Array.prototype.includes
const array1 = [0, 1, 2, 3];
const array2 = [1, 2];
for(let i in array1)
console.log(i, array2.includes(parseInt(i)));
You should use for..of with arrays and for..in with objects
The for...of statement creates a loop iterating over iterable objects,
including: built-in String, Array, array-like objects (e.g., arguments
or NodeList), TypedArray, Map, Set, and user-defined iterables. It
invokes a custom iteration hook with statements to be executed for the
value of each distinct property of the object. - MDN
const array1 = [0, 1, 2, 3];
const array2 = [1, 2];
for (let i of array1) console.log(array2.includes(i));
Alternate options
You can also use forEach here to achieve the exact same result:
const array1 = [0, 1, 2, 3];
const array2 = [1, 2];
array1.forEach((val) => console.log(array2.includes(val)));
for...in loops through all properties, not values. Arrays are objects, and their properties are 0 ... array.length, so i inside the for loop is 1, 2, 3 and 4.
You should be using a for...of loop instead:
const array1 = [0, 1, 2, 3];
const array2 = [1, 2];
for(let i of array1)
console.log(array2.includes(i));

Swapping array values with destructuring assignment and indexOf()

I'm trying to swap the two lowest values in a shuffled array containing the numbers 0-14. For those curious, I'm implementing the shuffling algorithm for a 15 puzzle described by pkpnd here.
I wanted to try destructuring assignment, as described here, but am encountering an unexpected behavior. I realize that I can get my code working (and make it more readable) by just creating a temporary variable, but I'd like to understand what's happening before moving on.
I'm grabbing a subset of my array [1,2] and then trying to replace it with [2,1]. For some reason, it's only swapping the values when their order in the original array is opposite of the order of my subset.
I originally tried this:
var arr1 = [1, 2, 3, 4];
var arr2 = [2, 1, 3, 4];
[arr1[arr1.indexOf(1)], arr1[arr1.indexOf(2)]] = [arr1[arr1.indexOf(2)], arr1[arr1.indexOf(1)]];
[arr2[arr2.indexOf(1)], arr2[arr2.indexOf(2)]] = [arr2[arr2.indexOf(2)], arr2[arr2.indexOf(1)]];
console.log("arr1: " + arr1, "\narr2: " + arr2);
And then tried this:
var arr1 = [1, 2, 3, 4];
var arr2 = [2, 1, 3, 4];
[arr1[arr1.indexOf(1)], arr1[arr1.indexOf(2)]] = [2, 1];
[arr2[arr2.indexOf(1)], arr2[arr2.indexOf(2)]] = [2, 1];
console.log("arr1: " + arr1, "\narr2: " + arr2);
But both produce identical output:
arr1: 1,2,3,4
arr2: 1,2,3,4
I would expect that the position of 1 and 2 would be swapped for both arrays, but they're only swapped in arr2. I suspect this has to do with they way the initial array subset [1,2] is created, but I'm not sure.
Can anybody explain why the values aren't always swapped?
The result is simple, because it goes step for step for each item of destructuring assingment. And while the values are changing, the index of the values changes.
Case 1 [1, 2, 3, 4]
Get index of target for the first value 2
[arr1[arr1.indexOf(1)], arr1[arr1.indexOf(2)]] = [2, 1];
// ^^^^^^^^^^^^^^^ 0
Assign 2 to arr1[0]
[2, 2, 3, 4]
Get index of target for the second value 1:
[arr1[arr1.indexOf(1)], arr1[arr1.indexOf(2)]] = [2, 1];
// ^^^^^^^^^^^^^^^ 0
Assign 1 to arr1[0]
[1, 2, 3, 4]
Case 2 [2, 1, 3, 4]
Get index of target for the first value 2
[arr2[arr2.indexOf(1)], arr2[arr2.indexOf(2)]] = [2, 1];
// ^^^^^^^^^^^^^^^ 1
Assign 2 to arr1[1]
[2, 2, 3, 4]
Get index of target for the second value 1:
[arr2[arr2.indexOf(1)], arr2[arr2.indexOf(2)]] = [2, 1];
// ^^^^^^^^^^^^^^^ 0
Assign 1 to arr1[0]
[1, 2, 3, 4]

How does a mutable array works in js?

i'm Learning Javascript from multiple ressources like FCC where i can't Understand one concept with the mutable arrays. I've got an example :
var myArray = [1,2,3];
myArray[0]=3; //[3,2,3]
var ourArray = [1,2,3];
ourArray[1] = 3; //[1,3,3]
i can't get how the [3,2,3] and [1,3,3] are created.
thanks for your help
ok, got it but what if my code looks like this :
var arr = [ [1,2,3], [4,5,6], [7,8,9], [[10,11,12], 13, 14] ];
arr[3]; // equals [[10,11,12], 13, 14] arr[3][0]; // equals [10,11,12]
arr[3][0][1]; // equals 11 how the arr[3] or arr[3][0] work ?
Arrays in JS starts with 0 index.
In the first case you're replacing 1 with 3
[1, 2, 3]
^
3
[0, 1, 2] <- indexes
In the second case, you're replacing 2 with 3
[1, 2, 3]
^
3
[0, 1, 2] <- indexes
Mutable just means that each element in the array can be changed.
The number inside the brackets is the order starting with 0;
So originally myArray[0] is 1, myArray[1] is 2, myArray[2] is 3
When you do myArray[0] = 3 it sets the value in the first spot to 3, hence getting 3,2,3
When you are writing myArray[0]=3 here you are setting a value of a particular position in that array same with ourArray[1] so you are making changes in that array with the new values so the console gives you array with new values like in your example you defined with the name myArray and ourArray .
Let me go through your code line by line,
var myArray = [1,2,3];
creates a myArray with [1, 2, 3]
myArray[0]=3;
index 0 of myArray is set to 3;
so myarray holds [3, 2, 3]
var ourArray = [1,2,3];
ourArray is created with [1, 2, 3]
ourArray[1] = 3;
index 1 of our array is set to 3;
so our array holds [1, 3, 3]
Please note that index starts with 0 and not with 1.

Javascript array is syncing with another assigned array

I've been racking my brain trying to figure out why these arrays are syncing after I assign one to the other. The output should be "1, 2, 3, 4" but instead it's "5, 6, 7, 8". Do I need to copy the arrays differently?
var firstArray = [1, 2, 3, 4];
var secondArray = [5, 6, 7, 8];
for (i = 0; i < firstArray.length; i++) {
var myTempArray = firstArray;
myTempArray[i] = secondArray[i];
}
console.log("Result: " + firstArray);
Expected output:
Result: 1,2,3,4
Actual output:
Result: 5,6,7,8
How do I alter the second array without changing the first array?
Arrays are mutable objects. So they just contain references. You need to "copy" an array in order to make a copy, not just assign like primitive objects. To copy an array, there are various methods. One best method is:
myTempArray = firstArray.slice();
What you are doing is a shallow copy:
Also, another big issue is that, you have the array assignment inside the loop, which keeps the myTempArray changing. You need to take it out of the loop. Your final code should look like:
var firstArray = [1, 2, 3, 4];
var secondArray = [5, 6, 7, 8];
var myTempArray = firstArray.slice();
for (i = 0; i < firstArray.length; i++) {
myTempArray[i] = secondArray[i];
}
console.log("Result: " + firstArray);

Merging arrays with passing a function as parameter

I've been on this problem for about 3 hours and I can't figure this out. I've gone through Codecademy and Code School Javascript courses, and according to the blog that hosted this code block, I should know the answer:
var merge = function(array1, array2, callback){
//your code here.
}
var x = merge([1, 2, 3, 4], [5, 6, 7, 8], function(a, b){
return a + b;
});
//x should now equal [6, 8, 10, 12].
UPDATED WITH CORRECT CODE (Thank you so much T.J.!):
var merge = function(array1, array2, callback) {
var i, newArray = [];
for (i=0; i < array1.length; i++) {
newArray[i] = callback(array1[i], array2[i]);
}
return newArray;
};
var x = merge([1, 2, 3, 4], [5, 6, 7, 8], function(a, b){
return a + b;
});
console.log(x);
In merge, you:
Create a new, blank array for the return value.
Consider what you want to do if array1 and array2 aren't the same length, although they are in the example usage.
Use an index variable to loop from 0 through < array1.length (most likely a for loop).
Fill in the entry for each index in your return value array by calling callback, passing the entry for that index from array1 and from array2 in as arguments and storing its return value in your array.
Return the new array.

Categories