javascript array.slice().push() not working as expected - javascript

The following code produces (in Chrome javascript console)
a: (3) [1, 2, 3] b: (4) [1, 2, 3, 99] c: 4
I expected c to look like b. Why doesn't it?
function snafu(){
var a = [1,2,3];
var b = a.slice();
var c = a.slice().push(99);
b.push(99);
console.log("a:",a," b:",b," c:",c);
}

Array.push() gives you value of Array.length and not array itself
var a = [];
var b = a.push(8); /* returns length of array after pushing value into array */
console.log('a = ', a, ', b = ', b);

Well, remember Array.slice() will return you new Array. So while pushing it on slice(), it'll return you length of the array.
function snafu(){
var a = [1,2,3];
var b = a.slice();
var c = a.slice();
c.push(99);
b.push(99);
console.log("a:",a," b:",b," c:",c);
}
snafu();
variable c will give you new Array so you can do whatever you want with c.
That's it. Easy!!!!

Related

Add to an array nested within associative array javascript

If I have an array that looks like
{X:{A,B,C},Y:{A,B,C}}
Where all the letters are variables
How would I add variable D to the array for the X variable key?
How would I add key Z variable to have the value of an array containing the A variable?
The equivalent of what I'm trying to do in php would just be
$array[x][] = d;
$array[z] = array(a,b);
You can access a multidimensional array like this:
var a = 1, b = 2, c = 3, d = 4;
var ary = [[a,b,c],[a,b,c]];
console.log(ary); //[[1,2,3],[1,2,3]];
ary[0].push(d); //add d to first array;
console.log(ary); //[[1,2,3,4],[1,2,3]];
You can also create an object to act like a lookup table.
var obj = {
x: [a, b, c],
y: [a, b, c]
}
console.log(obj); //{x: [1,2,3], y: [1,2,3]};
obj.x.push(d); //add d to array at x
console.log(obj); //{x: [1,2,3, 4], y: [1,2,3]};
obj.z = [d]; // add new key z with new array [d]
console.log(obj); //{x: [1,2,3, 4], y: [1,2,3], z: [4]};

Better way to handle operations with many variables?

I have around 30 values stored as variables:
var a = 1,
b = 2,
c = 3,
...
z = 26,
aa = 27,
ab = 28;
that I want to scale. I do so using an array:
array = [a, b, c];
var scale = 5;
for (var i = 0; i < array.length; i++){
array[i] = array[i] * scale; // Some simple arithmetic
}
To get the new scaled value, I need to reassign my variables.
var a = array[0],
b = array[1],
c = array[2],
...
z = array[26],
aa = array[27],
ab = array[28];
This is cumbersome, even if I use destructuring assignment. What is a better way to manage all the information I have?
Using plain variables you won‘t find a smarter way. I‘d suggest to use objects instead as arrays are anonymous because you access the content by index instead of a name:
let groupA = {
a: 1,
b: 2,
c: 3
}
You can then iterate and multiply via
for (let key in groupA) {
if (groupA.hasOwnProperty(key) {
groupA[key] *= 5;
}
}
but you still can access each field individually
console.log(groupA.a);
You have to reassign anyway, but you can do it in a more concise way:
let a = 1,
b = 2,
c = 3;
([a, b, c] = [a, b, c].map(v => v * 5));
console.log(b);

JS array problems - slice array 'b' and 'a' is sliced too

I have 2 arrays: A and B, when I change one both change. Is there a way to edit one without changing the other one.
a = [[0,0,0,0,0],[0,0,0,0,0]]
b = [[1,2,3,4,5],[6,7,8,9,10]]
a = b.slice(0)
a[0][0] = 10
console.log(a) /* [[10,2,3,4,5],[6,7,8,9,10]] */
console.log(b) /* [[10,2,3,4,5],[6,7,8,9,10]] */
The a is fine but I need b to stay [[1,2,3,4,5],[6,7,8,9,10]]
When you do splice, you change the reference of a and b, however, the reference of arrays in array b still share references, hence, update your code to following. Use Array.map
a = [[0,0,0,0,0],[0,0,0,0,0]]
b = [[1,2,3,4,5],[6,7,8,9,10]]
a = b.map(x => [...x])
a[0][0] = 10
console.log(a) /* [[10,2,3,4,5],[6,7,8,9,10]] */
console.log(b) /* [[1,2,3,4,5],[6,7,8,9,10]] */
You can use map to slice each array.
a = [[0,0,0,0,0],[0,0,0,0,0]]
b = [[1,2,3,4,5],[6,7,8,9,10]]
a = b.map(o=>o.slice(0));
a[0][0] = 10
console.log(a);
console.log(b);
Doc: map()
You take a shallow copy with Array#slice, which means nested arrays are taken by their object reference.
You could use Array#map with a check for arrays and map these recursively.
const deep = a => Array.isArray(a) ? a.map(deep) : a;
var a = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]],
b = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]];
a = b.map(deep);
a[0][0] = 10;
console.log(a);
console.log(b);
.as-console-wrapper { max-height: 100% !important; top: 0; }
slice(), like Object.freeze() have a shallow scope, so this works:
var a = [1,2,3,4];
var b = a.slice(0);
a[0] = 10;
console.log(b); // [1, 2, 3]
console.log(a); // [10, 2, 3, 4]
But this doesn't work:
var a = [[0,0,0,0,0],[0,0,0,0,0]]; //multidimensional!
var b = [[1,2,3,4,5],[6,7,8,9,10]];
a = b.slice(0);
a[0][0] = 10;
console.log(a);
console.log(b);
Then, the key is go deep with slice(), for or something, Here an example using for:
var a = [];
for (var i = 0, len = b.length; i < len; i++) {
a[i] = b[i].slice();
}
Keep in mind that const won't work:
var a = [[0,0,0,0,0],[0,0,0,0,0]];
const b = [[1,2,3,4,5],[6,7,8,9,10]];// doesn't work
var a = b.slice(0);
a[0][0] = 10; // a changes b
console.log(a);
console.log(b);

Merging arrays to form array of arrays in JavaScript (ES6)

I have an arrays:
a = [1, 1, 1, 1]
Which should be merged with an array of arrays:
b = [[0],[0],[0],[0]]
To form a third:
c = [[0,1],[0,1],[0,1],[0,1]]
One way I have thought would be to run a .forEach on a and concatenate to each object of b. however, I'd like this so the list may become longer with, for example d=[2,2,2,2] creating e=[[0,1,2],[0,1,2],[0,1,2],[0,1,2]].
a = [1, 1, 1, 1];
b = [[0],[0],[0],[0]];
a.forEach((number,index) => {
b[index] = b[index].concat(number)
});
console.log(b);
Thanks!
The concat method does not append, it creates a new array that you need to something with.
You want map, not forEach - and you mixed up a and b in whose elements need to be wrapped in an array literal to be concatenated:
var a = [1, 1, 1, 1];
var b = [[0],[0],[0],[0]];
var c = a.map((number, index) => {
return b[index].concat([number]);
});
// or the other way round:
var c = b.map((arr, index) => {
return arr.concat([a[index]]);
});
You could use reduce() method with forEach() and create new array.
let a = [1, 1, 1, 1], b = [[0],[0],[0],[0]], d=[2,2,2,2,2]
const result = [b, a, d].reduce((r, a) => {
a.forEach((e, i) => r[i] = (r[i] || []).concat(e))
return r;
}, [])
console.log(result)

Javascript code not working as expected

I am running this code and checking the log in firebug:
var a = new Array();
var b = new Array();
for (i=0; i<2 ; i++){
a.push(1);
b.push(a);
console.log("a", a);
console.log("b", b);
};
The log shows these values:
a [1]
b [[1]]
a [1,1]
b [[1,1],[1,1]]
According to me the values should be:
a [1]
b [[1]]
a [1,1]
b [[1],[1,1]]
What am I doing wrong and how could I get the values that I want?
When you're using .push to append a to the end of b, you're passing a reference and not ByVal as an Array is an Object. This means that future changes to a are reflected in the as already in b.
What you need is to .slice a when .pushing to b.
var a = new Array(), b = new Array();
for (i=0; i<2 ; i++) {
a.push(1);
b.push(a.slice());
console.log("a", a);
console.log("b", b);
};
/*
a [1]
b [[1]]
a [1, 1]
b [[1], [1, 1]]
*/

Categories