Why is my input parameter being modified in this code snippet? [duplicate] - javascript

This question already has answers here:
Copy array by value
(39 answers)
Closed 3 years ago.
Why is my input parameter inArr being modified when I update local variable arr in the JavaScript code below?
function test(inArr) {
var arr = inArr;
for (let i = 0; i < 3; i++) {
arr.push(i);
console.log( "arr = ", arr, "inArr = ", inArr );
}
}
test([]);
This outputs:
arr = [ 0 ] inArr = [ 0 ]
arr = [ 0, 1 ] inArr = [ 0, 1 ]
arr = [ 0, 1, 2 ] inArr = [ 0, 1, 2 ]

JavaScript arrays are assigned by reference, so when you make your assignment, both variables are pointing to the same array in memory. Any change to one will also change the other.
You can create a new array with those values using the spread operator:
var arr = [...inArray];

because they are the same.
function test(inArr) {
var arr = [].concat(inArr);
for (let i = 0; i < 3; i++) {
arr.push(i);
console.log( "arr = ", arr, "inArr = ", inArr );
}
}
test([]);

Related

New array from if statement results [duplicate]

This question already has answers here:
How to filter object array based on attributes?
(21 answers)
Closed 5 years ago.
I have an array containing objects.
I want to search the array using an if statement for objects that have a certain property and create a separate array containing only those objects.
var firstArray = [...]
for (var a = 0; a < firstArray.length; a++) {
if (firstArray[a].name == 'index.png') {
// create secondArray here
}
}
Thanks for your help!
Just use a filter
var secondArray = firstArray.filter(x => x.name == 'index.png')
var firstArray = [{
'name': 'A'
}, {
'name': 'B'
}, {
'name': 'C'
}]
var newArray = [];
for (name in firstArray) {
if (firstArray[name].name == 'A') {
newArray = firstArray[name];
console.log(newArray)
}
}
Kindly check this snippet.
You can use this way
var obj = {'el1': 1, 'el2': 2};
var firstArray = [{'el1': 1, 'el2': 2}, {'el3': 1, 'el4': 2}]
var searchTerm = 'el1';
for(var a=0; a<firstArray.length; a++){
for(var key in firstArray[a]){
if(key == searchTerm){
// do whatever you want to do.
console.log('key = ', key, 'value = ', obj[key]);
}
}
}

Using array as passing argument in javascript

var chessboard = [[2,1,0],[2,1,0],[0,0,0]];
function checkwins(array){}//The function is too long.I will explain here.It decides
//whether there is a winner.If there is a winner it will return 1 or 0
//(1 stand for number 2's win on the chessboard 0 stands for number 1's win)If there is no winner, it will return 2)
function score(board,depth){
if(checkwins(board)===0)return depth-10;
if(checkwins(board)==1)return 10-depth;
else return 0;
}
function count_move(board,depth,current_turn){
board = board.slice();
var possible_moves = possible_movements(board);
if(checkwins(board)!=2|| possible_moves.length===0)return score(board,depth);
var move_score;
var new_board;
depth++;
if(current_turn===0)move_score = -1000;
else move_score = 1000;
if(!current_turn){
possible_moves.forEach(function(possible_location){
var new_board = board.slice();
new_board[possible_location[0]][possible_location[1]] = 1;
var current_score = count_move(new_board,depth,1);
if(current_score > move_score)move_score = current_score;
});
}else{
possible_moves.forEach(function(possible_location){
var new_board = board.slice();
new_board[possible_location[0]][possible_location[1]] = 2;
var current_score = count_move(new_board,depth,0);
if(current_score < move_score)move_score = current_score;
});
}
return move_score;
}
function ai(board){
var possible_moves = possible_movements(board);
var best_move;
var move_score = -1000;
var current_score ;
possible_moves.forEach(function(move){
var next_board = board.slice();
next_board[move[0]][move[1]] = 1;
current_score = count_move(next_board,0,1);
console.log("Current Move :"+move+"\nCurrent Score :"+current_score+'\nCurrent Board :'+next_board+'\n');
if(current_score > move_score){
move_score = current_score;
best_move = move;
}
});
console.log(best_move);
}
console.log(chessboard);
ai(chessboard);
console.log(chessboard);
I am writing a Tic tac toe game Ai by using Minimax algorithm.I currently have some problems with javascript.I found that when I passed array as argument into function and then revise it in the function.It will change the array passing even outside the function.The console results is below:
[ [ 2, 1, 0 ], [ 2, 1, 0 ], [ 0, 0, 0 ] ]
Current Move :0,2
Current Score :-8
Current Board :2,1,1,2,1,2,2,2,2
Current Move :1,2
Current Score :10
Current Board :2,1,1,2,1,1,2,2,2
Current Move :2,0
Current Score :-10
Current Board :2,1,1,2,1,1,1,2,2
Current Move :2,1
Current Score :-10
Current Board :2,1,1,2,1,1,1,1,2
Current Move :2,2
Current Score :-10
Current Board :2,1,1,2,1,1,1,1,1
[ 1, 2 ]
[ [ 2, 1, 1 ], [ 2, 1, 1 ], [ 1, 1, 1 ] ]
Then I found it seems to use
new_array = array.slice()
inside the function should avoid it, so I add it in my function.The results still don't change.I get quite confused here.
slice performs a shallow copy of an array. That means that the array itself is copied but not any of the objects inside of it.
var a = [ [1], [2], [3] ];
var b = a.slice();
b.push(4);
// Change b does not change a
console.log('A:', JSON.stringify(a));
console.log('B:', JSON.stringify(b));
console.log('');
// However, changing the internal arrays will affect both
b[0][0] = 10;
console.log('A:', JSON.stringify(a));
console.log('B:', JSON.stringify(b));
console.log('');
You need to perform a deep copy, meaning you copy not just the outer array but also the inner arrays.
function copy2DArray(array) {
var copy = [];
array.forEach(function(subArray) {
var copiedSubArray = subArray.slice();
copy.push(copiedSubArray);
});
return copy;
}
var a = [ [1], [2], [3] ];
var b = copy2DArray(a);
// Now you won't change a by modifying b
b[0][0] = 10;
console.log('A:', JSON.stringify(a));
console.log('B:', JSON.stringify(b));

Count occurrences of array elements with JavaScript [duplicate]

This question already has answers here:
How to count duplicate value in an array in javascript
(35 answers)
Closed 7 years ago.
I have this JavaScript array with length 129.
var fullnames = [Karri, Ismo, Grigori, Ahmed, Roope, Arto .....]
I would like to find how many times those names appeared in an array and store that information in an array like this:
var counter = [2, 5, 7, ..]
where Karri occured in fullnames array 2 times, Ismo occured 5 times etc. Any ideas about how to do it?
This is the best - and simple - way I can think of:
var fullnames = ["Karri", "Ismo", "Grigori", "Ahmed", "Roope", "Ahmed", "Karri", "Arto", "Ahmed"];
var counts = {};
for (var i = 0; i < fullnames.length; i++)
{
if (!counts.hasOwnProperty(fullnames[i]))
{
counts[fullnames[i]] = 1;
}
else
{
counts[fullnames[i]]++;
}
}
console.log(counts);
Original Fiddle.
Using an array to store the counts doesn't makes much sense, so I used an object instead.
I am assuming that fullnames is array of strings. If so, you can do it like so:
var occurences = { };
for (var i = 0; i < fullnames.length; i++) {
if (typeof occurences[fullnames[i]] == "undefined") {
occurences[fullnames[i]] = 1;
} else {
occurences[fullnames[i]]++;
}
}
console.log(occurences); // Prints out something like: {"Karri": 2, "Ismo": 5, ...}
var fullnames = ['Karri', 'Ismo', 'Grigori', 'Karri', 'Ismo', 'Grigori', 'Grigori', 'Karri', 'Ismo', 'Grigori', 'Grigori'];
var counts = [];
fullnames.forEach(function(_item) {
if(typeof counts[_item] === 'undefined') counts[_item] = 1;
else counts[_item]++;
});
var result = [];
for(i in counts) result.push(counts[i]);
console.log(result);
// outputs [3, 3, 5]

Fill two-dimensional array per row

I have a function (getCoeff()) which returns one-dimensional arrays. I try to use it to fill a two-dimensional array:
//set up an 3x3 array for A
A = new Array(3);
for (var i=0; i<3; i++) {
A[i] = new Array(3);
}
//fill it per row using getCoeff()
for (var i=0; i<3; i++) {
A[i] = getCoeff(i+1);
}
console.log(A);
console.log(getCoeff(1));
console.log(getCoeff(2));
console.log(getCoeff(3));
but I only get the first row filled and the other two remain empty:
[ [ -3, 2, -1 ], [ , , ], [ , , ] ]
[ -3, 2, -1 ]
[ 2, -3, 2 ]
[ 1, -1, 3 ]
As you can see the function returns the rows correctly but for some reason It doesnt work inside the loop.
On the other hand if I try something like this:
for (var i=0; i<3; i++) {
A[i] = [1,2,3];
}
console.log(A);
it works fine!
[ [ 1, 2, 3 ], [ 1, 2, 3 ], [ 1, 2, 3 ] ]
What's wrong with my code?!
Update:
My original full code before the edits:
var fs = require('fs');
var input = "LPinput.txt";
var c = new Array();
var A = new Array();
var b = new Array();
var Eqin = new Array();
var MinMax;
open(input);
console.log(c);
console.log(A);
console.log(b);
console.log(Eqin);
console.log(MinMax);
function open(filename) {
if (fs.existsSync(filename)) {
var data = fs.readFileSync(filename).toString().split("\n");
analyse(data);
} else {
console.log("ERROR: File doesnt exist!");
}
}
function analyse(data) {
//clean up whitespaces
for (i in data) {
data[i] = data[i].replace(/\s/g, '');
}
//check LP type & clean up
if (data[0].substring(0,3) == "max") {
MinMax = 1;
data[0] = data[0].replace("max","");
} else if (data[0].substring(0,3) == "min") {
MinMax = -1;
data[0] = data[0].replace("min","");
} else {
console.log("ERROR: Invalid format!");
return;
}
//check constraints format & clean up
if ( data[1].substring(0,4) != "s.t.") {
console.log("ERROR: Invalid format!");
return;
} else {
data[1] = data[1].replace("s.t.","");
}
//get variables
var variables = data[data.length-1].split(",");
var last = variables[variables.length-1];
variables[variables.length-1] = last.substring(0,last.indexOf(">"));
//get number of constraints
var constraints = data.length-2;
c = getCoeff(0);
//===============================
//I JUST NEED TO POPULATE A TO FINISH THIS
for (var i=0; i<constraints; i++) {
A[i] = getCoeff(i+1);
}
//===============================
for (var i=1; i<data.length-1; i++) {
var end = data[i].length;
var start = end;
while (data[i].charAt(start) != "=") {
start = start - 1;
}
b[i-1] = parseInt(data[i].substring(start+1,end));
if (data[i].charAt(start-1) == "<") {
Eqin[i-1]=-1;
} else if (data[i].charAt(start-1) == ">") {
Eqin[i-1]=1;
} else {
Eqin[i-1]=0;
}
}
function getCoeff(row) {
var coeff = new Array();
for (i in variables) {
var pos = data[row].indexOf(variables[i]);
if ((data[row].charAt(pos-1) == "+") || (pos-1 < 0)) {
coeff[i]=1;
} else if (data[row].charAt(pos-1) == "-") {
coeff[i]=-1;
} else if (data[row].charAt(pos-1) == "*") {
var end = pos-1;
var start = end;
while ( (start > -1) && (data[row].charAt(start) != "+") && (data[row].charAt(start) != "-") ) {
start = start - 1;
}
coeff[i] = parseInt((data[row].substring(start,end)));
}
}
return coeff;
}
}
LPinput.txt:
max 2*x1+x2-4*x3-15
s.t.-3*x1+2*x2-x3>=5
2*x1-3*x2+2*x3<=9
x1-x2+3*x3<=5
x1,x2,x3>=0
Update #2:
Console output:
[ 2, 1, -4 ]
[ [ -3, 2, -1 ] ]
[ 5, 9, 5 ]
[ 1, -1, -1 ]
1
It should be:
[ 2, 1, -4 ]
[ [ -3, 2, -1 ],[ 2, -3, 2 ],[ 1, -1, 3 ]]
[ 5, 9, 5 ]
[ 1, -1, -1 ]
1
Here is the real problem:
you are using an i variable in your outer scope.
for (var i=0; i<constraints; i++) {
A[i] = getCoeff(i+1);
}
When you go inside the getCoef you have this for loop
for (i in variables) {
and since you have not declared the i here, it uses the same i declared in the outer scope. After the first run of the for loop (which fills the first row of A), i is changed to "0" as opposed to the numeric value 0. Therefore the condition of the for loop is no longer valid and it exits the loop.
There you go!
In my case, I got last 2 populated. Anyways, if you run loop from 0, you better write
A[i] = getCoeff(i+1);
OR
you run that loop starting from 1 to less than equals 3.
In your code:
A = new Array(3);
you should declare varaibles, and initialising an array with a length is usually unnecessary. Also, variables starting with a capital letter are, by convention, reserved for construtors (though some use variable names in all capitals to represent constants).
Consider using an array initialiser:
var a = [];
for (var i=0; i<3; i++) {
Initialising arrays in the following loop is a bit useless as you replace them in the next loop:
a[i] = [];
}
In the next loop, i is needlessly declared again (there is no block scope in javascript). It is common to use a different variable in these cases (though re-using i has no ill effects, it's just not liked):
for (var j=0; j<3; j++) {
a[j] = getCoeff(j + 1);
}
So creating a getCoeff function that just returns an array of the value passed to it (purely for testing):
function getCoeff(v){
return [v,v,v];
}
"works":
console.log(a.join(' - ')); // 1,1,1 - 2,2,2 - 3,3,3

How can I find matching values in two arrays? [duplicate]

This question already has answers here:
Simplest code for array intersection in javascript
(40 answers)
Closed 3 years ago.
I have two arrays, and I want to be able to compare the two and only return the values that match. For example both arrays have the value cat so that is what will be returned. I haven't found anything like this. What would be the best way to return similarities?
var array1 = ["cat", "sum","fun", "run"];
var array2 = ["bat", "cat","dog","sun", "hut", "gut"];
//if value in array1 is equal to value in array2 then return match: cat
You can use :
const intersection = array1.filter(element => array2.includes(element));
Naturally, my approach was to loop through the first array once and check the index of each value in the second array. If the index is > -1, then push it onto the returned array.
​Array.prototype.diff = function(arr2) {
var ret = [];
for(var i in this) {
if(arr2.indexOf(this[i]) > -1){
ret.push(this[i]);
}
}
return ret;
};
​
My solution doesn't use two loops like others do so it may run a bit faster. If you want to avoid using for..in, you can sort both arrays first to reindex all their values:
Array.prototype.diff = function(arr2) {
var ret = [];
this.sort();
arr2.sort();
for(var i = 0; i < this.length; i += 1) {
if(arr2.indexOf(this[i]) > -1){
ret.push(this[i]);
}
}
return ret;
};
Usage would look like:
var array1 = ["cat", "sum","fun", "run", "hut"];
var array2 = ["bat", "cat","dog","sun", "hut", "gut"];
console.log(array1.diff(array2));
If you have an issue/problem with extending the Array prototype, you could easily change this to a function.
var diff = function(arr, arr2) {
And you'd change anywhere where the func originally said this to arr2.
I found a slight alteration on what #jota3 suggested worked perfectly for me.
var intersections = array1.filter(e => array2.indexOf(e) !== -1);
Hope this helps!
This function runs in O(n log(n) + m log(m)) compared to O(n*m) (as seen in the other solutions with loops/indexOf) which can be useful if you are dealing with lots of values.
However, because neither "a" > 1 nor "a" < 1, this only works for elements of the same type.
function intersect_arrays(a, b) {
var sorted_a = a.concat().sort();
var sorted_b = b.concat().sort();
var common = [];
var a_i = 0;
var b_i = 0;
while (a_i < a.length
&& b_i < b.length)
{
if (sorted_a[a_i] === sorted_b[b_i]) {
common.push(sorted_a[a_i]);
a_i++;
b_i++;
}
else if(sorted_a[a_i] < sorted_b[b_i]) {
a_i++;
}
else {
b_i++;
}
}
return common;
}
Example:
var array1 = ["cat", "sum", "fun", "hut"], //modified for additional match
array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];
intersect_arrays(array1, array2);
>> ["cat", "hut"]
Loop through the second array each time you iterate over an element in the first array, then check for matches.
var array1 = ["cat", "sum", "fun", "run"],
array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];
function getMatch(a, b) {
var matches = [];
for ( var i = 0; i < a.length; i++ ) {
for ( var e = 0; e < b.length; e++ ) {
if ( a[i] === b[e] ) matches.push( a[i] );
}
}
return matches;
}
getMatch(array1, array2); // ["cat"]
var array1 = [1, 2, 3, 4, 5, 6];
var array2 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var array3 = array2.filter(function(obj) {
return array1.indexOf(obj) !== -1;
});
You can use javascript function .find()
As it says in MDN, it will return the first value that is true. If such an element is found, find immediately returns the value of that element. Otherwise, find returns undefined.
var array1 = ["cat", "sum", "fun", "run", "cat"];
var array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];
found = array1.find((val, index) => {
console.log('index', index) // Stops at 0
return array2.includes(val)
})
console.log(found)
Or use .filter(), which loops through every elements first, then give back the result to you.
var array1 = ["cat", "sum", "fun", "run", "cat"];
var array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];
found = array1.filter((val, index) => {
console.log('index', index) // Stops at array1.length - 1
return array2.includes(val)
})
console.log(found)
use lodash
GLOBAL.utils = require('lodash')
var arr1 = ['first' , 'second'];
var arr2 = ['second '];
var result = utils.difference(arr1 , arr2);
console.log ( "result :" + result );
Libraries like underscore and lodash have a utility method called intersection to find matches in arrays passed in. Take a look at: http://underscorejs.org/#intersection
Done as a answer so I can do formatting...
This is the the process you need to go through. Looping through an array for the specifics.
create an empty array
loop through array1, element by element. {
loop through array2, element by element {
if array1.element == array2.element {
add to your new array
}
}
}
If your values are non-null strings or numbers, you can use an object as a dictionary:
var map = {}, result = [], i;
for (i = 0; i < array1.length; ++i) {
map[array1[i]] = 1;
}
for (i = 0; i < array2.length; ++i) {
if (map[array2[i]] === 1) {
result.push(array2[i]);
// avoid returning a value twice if it appears twice in array 2
map[array2[i]] = 0;
}
}
return result;
With some ES6:
let sortedArray = [];
firstArr.map((first) => {
sortedArray[defaultArray.findIndex(def => def === first)] = first;
});
sortedArray = sortedArray.filter(v => v);
This snippet also sorts the firstArr based on the order of the defaultArray
like:
let firstArr = ['apple', 'kiwi', 'banana'];
let defaultArray = ['kiwi', 'apple', 'pear'];
...
console.log(sortedArray);
// ['kiwi', 'apple'];
Iterate on array1 and find the indexof element present in array2.
var array1 = ["cat", "sum","fun", "run"];
var array2 = ["bat", "cat","sun", "hut", "gut"];
var str='';
for(var i=0;i<array1.length;i++){
if(array2.indexOf(array1[i]) != -1){
str+=array1[i]+' ';
};
}
console.log(str)

Categories

Resources