This question already has answers here:
Accessing an object property with a dynamically-computed name
(19 answers)
Closed 4 years ago.
Here's my code:
headersObj = {a: "a", b: "b", c: "c"};
headers = ["a", "b", "c"];
fields = ["a", "b"];
notInTemplate = [];
headers.forEach(function(obj) {
if(fields.indexOf(obj) == '-1'){
console.log(headersObj.c);
console.log(headersObj.obj);
console.log(obj);
notInTemplate.push(obj);
}
});
console.log(notInTemplate);
I could explain more about my use case, but I just want to be able to "headersObj" property, so I can push it to the "notInTemplate" array. I've distilled it to this fairly simple example. The output of which is:
c
undefined
c
[ 'c' ]
Why is the object property undefined?
You have to use bracket notation ([]) to access the object's property dynamically:
headersObj = {a: "a", b: "b", c: "c"};
headers = ["a", "b", "c"];
fields = ["a", "b"];
notInTemplate = [];
headers.forEach(function(obj) {
if(fields.indexOf(obj) == '-1'){
console.log(headersObj.c);
console.log(headersObj[obj]);
console.log(obj);
notInTemplate.push(obj);
}
});
console.log(notInTemplate);
Related
This question already has answers here:
How to filter an array from all elements of another array
(24 answers)
Closed 2 years ago.
const arr1 = ["a", "b", "c", "d", "e"];
const arr2 = ["b", "d"];
I need to do something which remove "b" and "d" from arr1. Of course I need to remove elements from arr1 which exist in arr2 too.
Try using filter + includes:
const arr1 = ["a", "b", "c", "d", "e"];
const arr2 = ["b", "d"];
let result = arr1.filter(el => !arr2.includes(el));
console.log(result);
This question already has answers here:
Variable name as a string in Javascript
(20 answers)
Closed 4 years ago.
var a = "aa", b= "bb",c ="cc", d="dd", e="ee";
array = [a,b,c,d,e] // outputs ["aa", "bb", "cc", "dd", "ee"];
However is there a possibility in javascript to convert the variables (a, b,c,d,e) into strings?
Like: "a", "b", "c", "d", "e"??
P.S: the array values could be dynamic as well or more than the length mentioned above.
Thanks for the help!!
You could do this with ES6 shorthand property names and return array of strings.
let a = "aa", b= "bb",c ="cc", d="dd", e="ee";
let strings = Object.keys({a, b, c, d, e});
console.log(...strings)
Something like this
var a = "aa", b= "bb",c ="cc", d="dd", e="ee";
var array = [a,b,c,d,e];
({a,b,c,d,e} = array)
var keys = Object.keys({a,b,c,d,e});
console.log(keys)
console.log(array)
I'm trying to create a music game where I have to generate a 3D array from a basic 2D array. The plan was to copy and paste the 2D array 4 times into the 3D array before modifying it, as shown:
var note3base = [
["C", "E", "G"],
["C#", "E#", "G#"],
["Db", "F", "Ab"],
["D", "F#", "A"],
["Eb", "G", "Bb"],
["E", "G#", "B"],
["F", "A", "C"],
["F#", "A#", "C#"],
["Gb", "Bb", "Db"],
["G", "B", "D"],
["Ab", "C", "Eb"],
["A", "C#", "E"],
["Bb", "D", "F"],
["B", "D#", "F#"],
["Cb", "Eb", "Gb"]
];
var note3 = new Array(4);
for (h=0;h<note3.length;h++){
note3[h] = note3base;
} //creates 4 copies of note3base in a 3d-array to be modified
for (i=0;i<note3[0].length;i++){
note3[1][i][1] = flat(note3[1][i][1]); //minor
note3[2][i][1] = flat(note3[2][i][1]);
note3[2][i][2] = flat(note3[2][i][2]); //dim
note3[3][i][2] = sharp(note3[3][i][2]); //aug
} //how did everything become the same?
The problem now seems to be that the for loop seems to apply the method to every single array (0 through 3).
The desired output for note3[0][1] would be C E G, note3[1][1] would be C Eb G, note[2][1] would be C Eb Gb, note[3][1] would be C E G#.
Any help is greatly appreciated!
I've included the (working) sharp and flat methods below for reference:
function sharp(note){
var newnote;
if (note.charAt(1) == "#"){
newnote = note.replace("#", "x");
} else if (note.charAt(1) == "b"){
newnote = note.replace("b", "");
} else {
newnote = note + "#";
}
return newnote;
}
function flat(note){
var newnote;
if (note.charAt(1) == "#"){
newnote = note.replace("#", "");
} else {
newnote = note + "b";
}
return newnote;
}
The problem is that when you assign a variable equal to an array like this:
someVar = someArray;
...it doesn't make a copy of the array, it creates a second reference to the same array. (This applies to all objects, and arrays are a type of object.) So after your loop, where you've said:
for (h=0;h<note3.length;h++){
note3[h] = note3base;
...all of the elements in note3 refer to the same underlying array.
To make an actual copy, you can manually copy all of the elements across using a loop, or you can use the .slice() method to make a copy for you:
for (h=0;h<note3.length;h++){
note3[h] = note3base.slice();
}
But that will only solve half of the problem, because note3base itself contains references to other arrays, and .slice() will just copy these references. That is, although note3[0] and note3[1] (and 2 and 3) will refer to different arrays, note3[0][0] and note3[1][0] and note3[2][0] and note3[3][0] will refer to the same ["C", "E", "G"] array. (And so forth.)
You need what's called a "deep copy". You could do it with a nested loop:
for (h=0;h<note3.length;h++){
// create this element as a new empty array:
note3[h] = [];
// for each 3-note array in note3base
for (var k = 0; k < note3base.length; k++) {
// make a copy with slice
note3[h][k] = note3base[k].slice();
}
}
Having said all that, I think an easier way to do the whole thing would be instead of having a note3base variable that refers to an array, make it a function that returns a new array:
function makeNote3Array() {
return [
["C", "E", "G"],
["C#", "E#", "G#"],
["Db", "F", "Ab"],
["D", "F#", "A"],
["Eb", "G", "Bb"],
["E", "G#", "B"],
["F", "A", "C"],
["F#", "A#", "C#"],
["Gb", "Bb", "Db"],
["G", "B", "D"],
["Ab", "C", "Eb"],
["A", "C#", "E"],
["Bb", "D", "F"],
["B", "D#", "F#"],
["Cb", "Eb", "Gb"]
];
}
Because the function uses an array literal it will create a brand new array of arrays every time it is called. So then you can do the following, with no need for .slice() or nested loops:
var note3 = new Array(4);
for (h=0;h<note3.length;h++){
note3[h] = makeNote3Array();
}
TL;DR, do this:
for (h=0;h<note3.length;h++){
note3[h] = note3base.slice(0);
}
Explanation:
The problem is coming from the difference between passing something'by value' and 'by reference' in Javascript.
When you assign a primitive value to a variable, like a = "string";, and then assign that to another variable, like b = a;, the value is passed to b 'by-value': its value is assigned to b, but b references a different part of memory. There are now two "string" values in the memory, one for a, and one for b.
a = "string";
b = a;
a = "gnirts";
console.log(b); // "string"
This is not how it works for non-primitive types, such as arrays. Here the value is passed to b 'by reference', meaning that there is still only one [1, 2, 3] array in the memory, and both a and b are pointing at it. This means that is you change an element in a, it will change for b as well, because they reference the same array in memory. So you get this:
a = [1, 2, 3];
b = a;
a[0] = "hello";
console.log(b); // ["hello", 2, 3]
b[0] has changed because it references the same location in memory as a[0]. To get around this problem, we need to explicitly make a copy of note3base when passing it to another variable, rather than just passing it by reference. We can do this with note3base.slice(0) as above.
Edit: read more here
This question already has answers here:
Copy array by value
(39 answers)
Closed 8 years ago.
I need to make a temporary copy of a variable to make changes to. Here's what I mean:
var x = ["a", "b", "c"];
var y = x;
y[1] = "2"
//x: ["a", "b", "c"];
//y: ["a", 2, "c"];
It's worth pointing out that I'm using an object I defined myself, and not a built in data structure.
The standard method for 'cloning' array of primitive types in JavaScript (based on your requirements) is shown below:
var x = ["a", "b", "c"];
var y = x.slice(0);
y[1] = "2";
Be aware, that if array contains complex types (objects), then it will keep original references; in other words, it does not perform 'deep' copy on array of objects.
Try this
var x = ["a", "b", "c"];
var y = JSON.parse(JSON.stringify(x));
//y = ["a", "b", "c"];
Then u can manipulate your new object as u want.
You can use jQuery to clone your object
var newObject = jQuery.extend(true, {}, oldObject);
jQuery Documentation
I have the following problem with .push() method:
var myArray = ["a", "b", "c", "d"];
function add(arr) {
arr.push("e");
return arr;
}
add(myArray);
// myArray is now ["a", "b", "c", "d", "e"]
Why it overrides myArray? Can't understand that...
Arrays in Javascript (and most other languages) are passed by reference.
When you write add(myArray), you are passing a reference to the same Array instance that the global myArray variable refers to.
Any changes to the array object will be visible through both references.
To copy the actual array instance, write add(myArray.slice());.
Note that this will not copy the objects inside of it.
If you need to be able to nest arrays, then I'd change the .add() function to have the .concat() duplicate the Array into a variable, .push() the new value into the new Array, and return it.
function add(arr) {
var newArr = arr.concat(); // duplicate
newArr.push("e"); // push new value
return newArr; // return new (modified) Array
}
You could use concat() as well, and return the new array it creates.
var myArray = ["a", "b", "c", "d"];
function add(arr) {
return arr.concat("e");
}
var newArray = add(myArray);
console.log( newArray ); // ["a", "b", "c", "d", "e"]
console.log( myArray ); // ["a", "b", "c", "d"]
So instead of two methods .slice() then .push(), you accomplish it with one .concat().
This also gives you the benefit of passing another Array instead of a string, so:
return arr.concat(["e","f"]);
would give you:
// ["a", "b", "c", "d", "e", "f"]
instead of:
// ["a", "b", "c", "d", ["e", "f"] ]