I have made an array and placed some variables in it, and I want to get the name of the variable using the index number.
var a = 0;
var b = 0;
var c = 0;
var letters = [a,b,c]
console.log(letters)
I want to have it output "[ a, b, c ]" but this code actually outputs "[0, 0, 0]"
For more context, I plan to take the values of a, b, and c and then sort them based on their values, but then I still want to be able to see their variable names in the new order after they have been sorted.
You can use a object instead, You can get keys as an array using Object.keys and later you sort them
const obj = {
a: 0,
b: 2,
c: 1
};
console.log(Object.keys(obj));
//sort keys based on values
const sorted = Object.keys(obj).sort((a,b)=> obj[a]-obj[b])
console.log(sorted)
Use an object indexed by those variable names instead, and then you can take that object's Object.keys, which will give you an array of the properties:
const obj = {
a: 0,
b: 0,
c: 0
};
console.log(Object.keys(obj));
I want to get the name of the variable using the index number.
Access that index in the Object.keys array, eg Object.keys(obj)[1] will evaluate to b.
To sort, take the Object.entries of the object (which will give you both the key and value at once):
const obj = {
a: 0,
b: 2,
c: 1
};
console.log(
Object.entries(obj)
.sort((a, b) => a[1] - b[1])
);
You can't do it with an array - you'd have to use an object. You can get the keys with Object.keys, and the values with Object.values:
var a = 0;
var b = 0;
var c = 0;
var letters = {a, b, c};
console.log(Object.keys(letters));
console.log(Object.values(letters));
.as-console-wrapper { max-height: 100% !important; top: auto; }
This might resolve your problem:
var variableName = 0;
console.log(Object.keys({
variableName
})[0]);
Related
const [a, b, c] = array;
const {a, b, c} = array;
Q: what is the difference here in both the statements?
The first is iterable destructuring. a will get the first value in array, b will get the second, and c will get the third.
The second is object destructuring. a will get the value of array.a, b will get the value of array.b, and c will get the value of array.c. (Not usually what you want with arrays.)
Example of the first:
const [a, b, c] = ["ay", "bee", "see"];
console.log(a, b, c);
That example uses an array, but the source can be any iterable object.
Example of the second (object destructuring), with an array:
const array = ["ay", "bee", "see"];
const {a, b, c} = array;
console.log(a, b, c);
In the normal case, of course, those will all be undefined (as they are above), because arrays don't normally have those properties.
Example of the second (object destructuring), with a non-array object:
const obj = {a: "ayy", b: "bee", c: "see"};
const {a, b, c} = obj;
console.log(a, b, c);
You don't normally use object destructuring with arrays, although you can, since arrays are objects. The times it's useful are when you want to pick out specific entries from the array, such as this code picking out the values at indexes 2 and 4:
const array = ["ay", "bee", "see", "dee", "eee"];
const {2: c, 4: e} = array;
console.log(c, e); // "see" "eee"
You can even do that with indexes from a variable using computed property notation in the destructuring pattern:
const array = ["ay", "bee", "see", "dee", "eee"];
const indexA = Math.floor(Math.random() * array.length);
const indexB = Math.floor(Math.random() * array.length);
const {[indexA]: a, [indexB]: b} = array;
console.log(`${indexA}: ${a}, ${indexB}: ${b}`); // Varies depending on the random indexes
More on MDN.
These are array de-structuring and object de-structuring in ES6 Javascript.
To demonstrate with example,
const [a, b, c] = [10, 11, 12];
From the above array destructuring statement:
a, b and c are the variables declared and intialized with 10, 11 and 12 values respectively.
const person = {
first: 'abc',
last: 'def',
};
const {first, last} = person;
From the above object destructuring statement,
first and last are varialbes declared and initialised with 'abc' and 'def' respectively.
The variable first and second accessed (gets the value) like person.first and person.last respectively
Example 1 is array destructuring, it assigns array elements (array[0], etc) to respective variables. It's applicable only to iterables, which arrays are:
const array = [0, 1];
const [a, b] = array;
// a === 0;
// b === 1;
Example 2 is object destructuring, it assigns object key values to respective variables. Since an array is an object in JS, const {a, b} = ... object destructuring is applicable to an array only if it has non-numeric keys:
const array = [0, 1];
array.a = 'a';
array.b = 'b';
const {a, b} = array;
// a === 'a';
// b === 'b';
Object destructuring can in fact be used to destructure arrays because they are objects that consist of numeric keys:
const array = [0, 1];
const {0: a, 1: b} = array;
// a === 0;
// b === 1;
It is possible to do:
let a = 1,
b = 3,
c = 9;
Is it also possible to do:
obj.a = 1,
b = 2,
c = 3;
This is still very readable, but a lot less typing, then writing obj a lot of times.
If the variables are already defined, you can use shorthand property names to define the object in one go, without any repetition:
const obj = { a, b, c };
You can assign the defined variables using shorthand property names
let a = 1,
b = 3,
c = 9;
let obj = {a,b,c}
console.log(obj)
If there exists a relation between the property names and the values then one can write a compact object definition using map. Otherwise one can just initialize the object with names and values.
// function
var obj = {};
['a', 'b', 'c'].map((x, i) => (obj[x] = i));
console.log(obj);
// no function
var obj1 = {a: 1, b: 2, c: 4};
console.log(obj1);
If the variables are not already assigned, you could use Object.assign:
const obj = Object.assign({}, { a: 1, b: 2, c: 3 });
console.log(obj);
Otherwise, use ES6 shorthand property notation:
const [a, b, c] = [1, 2, 3];
const obj = { a, b, c };
console.log(obj);
You can do this (if object is re-assignable ex: let NOT const ):
obj = {...obj, a : 1,
b : 2,
c: 3,
}
Thank you :)
var arr = [{a: "one", b: "two"}];
/* in real code I have actual filter condition, but the filtered result
share some common properties with value */
var res = {
arr1: arr.filter(x => x),
arr2: arr.filter(x => x)
};
res.arr1.forEach(x => x.a = "a");
console.log(arr); //should print [{a: "one", b: "two"}]
console.log(res.arr1); //should print [{a: "a", b: "two"}]
console.log(res.arr2); //should print [{a: "one", b: "two"}]
If I change the values in arr1 array of object res then why the changes are applied to the arr2 and res also? filter creates new array then the effect should not be applied.
What I am doing wrong here?
Each element in the new array keeps the same object reference so you need to clone the object. In case there is no nested value then you can use Object.assign along with Array#map method. For deeper cloning, you need to use some other library or need to implement your own custom function.
var arr = [{a: "one", b: "two"}];
/* in real code I have actual filter condition, but the filtered result
share some common properties with value */
var res = {
arr1: arr.map(x => Object.assign({}, x)),
arr2: arr.map(x => Object.assign({}, x))
};
res.arr1.forEach(x => x.a = "a");
console.log(arr); //should print [{a: "one", b: "two"}]
console.log(res.arr1); //should print [{a: "a", b: "two"}]
console.log(res.arr2); //should print [{a: "one", b: "two"}]
FYI : What is the most efficient way to deep clone an object in JavaScript?
The reason is that the array contains references to the objects, not copies of them. So while filter does returns a new array, the objects inside them still reference to the same objects.
So, when forEach is mutating the object referenced in res.arr1, it is modifying objects in all the arrays as they all point to the same reference.
Hope this helps.
Your items in the array are objects - they are reference types. Means that you have only one object and the rests are references to that same object. So changing it from one reference affects the result reading from another reference. You need to copy the items from the array. Here I used property spreading to copy the objects.
var arr = [{a: "one", b: "two"}];
var res = {
arr1: arr.map(x => ({...x})),
arr2: arr.map(x => ({...x}))
};
res.arr1.forEach(x => x.a = "a");
console.log(arr);
console.log(res.arr1);
console.log(res.arr2);
When you write :
xs = [
{ p : true },
{ p : false }
];
ys = xs.filter(
x => x.p
);
Here is how it looks like in memory :
xs { p : false }
\ /
[ 0 , 1 ]
\
{ p : true }
/
[ 0 ]
/
ys
As you said, .filter() creates a new array, that's why xs and ys are linked to different arrays. Then, since xs[0].p is true, it makes a copy of xs[0] and pushes it to the new array. What you need to realize here is that xs[0] is a link to { p : true }, it's not the object itself, and ys[0] is a copy of this link. As a consequence, xs[0] and ys[0] are linked to the same object, and if you write xs[0].p = false, you can read the update with ys[0].p.
xs[0]
\
{ p : false }
/
ys[0]
If you want to avoid this situation, you have to copy the object itself :
function copy (x) {
var y = {}; // new object
for (var k in x) y[k] = x[k];
return y;
}
ys[0] = copy(ys[0]);
Since copy() returns a new object, xs[0] and ys[0] are now linked to different objects, thus, changes to one object won't affect the other :
xs[0].p = true;
xs[0] --- { p : true }
ys[0] --- { p : false }
Regarding your code, arr[0] is a link to { a: "one", b: "two" }, and .filter() creates new arrays that contains a copy of this link pointing to the same object :
res.arr1[0]
\
\
arr[0] ----- { a: "one", b: "two" }
/
/
res.arr2[0]
Again, if you want to avoid this situation, you have to copy the object itself. However, since arr is likely to contain more than one object, you have to iterate over the array to copy every object one after the other. .map() is perfect for this job :
res.arr1 = arr.filter(f).map(copy);
res.arr2 = arr.filter(f).map(copy);
res.arr1[0] --- { a: "one", b: "two" }
arr[0] -------- { a: "one", b: "two" }
res.arr2[0] --- { a: "one", b: "two" }
Be careful though, it's a bit trickier when it comes to nested objects :
xs = [{ p: {} }]; // nested objects
ys = [copy(xs[0])];
In the above case, xs[0] and ys[0] are different, but xs[0].p and ys[0].p are the same :
xs[0]
\
{ p }
\
{}
/
{ p }
/
ys[0]
In such a case, you have to make a deep copy of the object. This function will do the trick :
function copyTree (x) {
if (x instanceof Array) {
var copy = [];
for (var i = 0; i < x.length; i++) {
copy[i] = copyTree(x[i]);
}
return copy;
} else if (x === Object(x) && typeof x !== "function") {
var copy = {};
for (var k in x) {
copy[k] = copyTree(x[k]);
}
return copy;
} else {
return x;
}
}
res.arr1 = arr.filter(f).map(copyTree);
res.arr2 = arr.filter(f).map(copyTree);
Note that the same problem arises with nested arrays, hence the array test above.
This question already has answers here:
Sorting object property by values
(44 answers)
Closed 6 years ago.
I have a list of strings, I want to check if the string contains a specific word, and if it does split all the words in the string and add it to an associative array.
myString = ['RT #Arsenal: Waiting for the international', 'We’re hungry for revenge #_nachomonreal on Saturday\'s match and aiming for a strong finish']
wordtoFind = ['#Arsenal']
I want to loop through the wordtoFind and if it is in myString, split up myString into individual words and create an object like
newWord = {#Arsenal:{RT:1},{Waiting:1},{for:1},{the:1},{international:1}}
for(z=0; z <wordtoFind.length; z++){
for ( i = 0 ; i < myString.length; i++) {
if (myString[i].indexOf(wordtoFind[z].key) > -1){
myString[i].split(" ")
}
I am currently stuck and I am not sure how to continue.
You can't do it. key value objects are not sorted by keys.
take a look at Does JavaScript Guarantee Object Property Order
you can turn it into a sorted array.
// Turn to array
var arr = [];
for(var key in mydict) {
arr.push({key: key, val: mydict[key]})
}
// Sort
arr.sort(function(a, b) {
return a.val - b.val;
})
Use temporary array for sorting your values
var dict = { a: 5, b: 9, z: 21, n: 1, y: 0, g: 3, q: 6 }
var a = Object.keys(dict).map(e => ({ key: e, val: dict[e] }))
.sort((a, b) => a.val - b.val).slice(0, 5);
var r = {};
a.forEach(e => r[e.key] = e.val);
document.write(JSON.stringify(r));
When I try to make a function to swap 2 arrays, the original arrays are left unaltered.
function swap(x, y) {
var temp = x; x = y; y = temp;
}
u=[1, 0];
v=[0, 1];
swap(u, v);
console.log(u);
console.log(v);
This results in u as [1, 0] and v as [0, 1]. The values haven't been changed after the function call to swap.
On the other hand, if I do this without a function call:
u=[1, 0];
v=[0, 1];
var temp = u;
u = v;
v = temp;
console.log(u);
console.log(v);
Then they're swapped correctly, with u as [0, 1] and v as [1, 0].
I thought Javascript arrays are passed by reference, not by value. Am I misunderstanding something here?
Javascript does not have the ability to pass a reference to the u and v variables themselves. So, no assignment to x or y in your swap() function will change what is assigned to u or v. Javascript passes a reference to the object that u and v hold. Thus, you can't change the u and v variables from within swap(). You can change the contents of the object that they point to and thus properties of the object that u and v point to can be modified.
Since I have a C/C++ background, I think of what Javascript does when passing objects as "pass by pointer". When you call swap(u, v), what is passed to the swap() function is a pointer to the array that u also points to. So, now you have two variables u and x both "pointing" at the same array. Thus, if you modify that actual array, then since u points at that same array, both will see the modification. But, nothing you do inside the swap() function can change what object u or v actually point to.
In Javascript, the only way to change what object the original variables point to is to make them properties of an object and pass the object like this:
function swap(obj, x, y) {
var temp = obj[x]; obj[x] = obj[y]; obj[y] = temp;
}
var container = {};
container.u = [1, 0];
container.v = [0, 1];
swap(container, "u", "v");
console.log(container.u);
console.log(container.v);
If you don't mind rewriting both arrays from scratch, you can copy all the contents of one array to a temporary, then copy one array over to the other and then copy the temporary array contents back to the first original. This is not very efficient and there is probably a better way to solve your original problem, but it can be done.
function swap(x, y) {
// remove all elements from x into a temporary array
var temp = x.splice(0, x.length);
// then copy y into x
x.push.apply(x, y);
// clear y, then copy temp into it
y.length = 0;
y.push.apply(y, temp);
}
Getting the terminology on these "reference/value" questions is tricky, but I will do my best.
What you have for your Object / Array variables are really just references. Unlike C++, saying "x = y" does not actually copy the object's variables over to a new memory location. Internally, it's just copying a pointer location over. The language does not have constructions to "automatically recreate" something like an object or array in a new instance; if for some reason, you want to maintain two copies of an array, you will need to explicitly create it then copy over values (ie, = []; or = new Array(); or a copying function like = oldArray.map(...))
A little code example that might conceptually help. These same rules apply between objects and arrays.
a = {}; // In case you haven't seen it, this is like shorthand of "new Object();"
b = {};
c = b;
console.log(a === b); // false
console.log(b === c); // true
b.property = "hello";
console.log(c.property) // hello
Just like Java, JavaScript is pass-by-value only. Assigning to local variables in a function never has any effect on anything outside the function.
They are passed by reference, but they are also assigned by reference. When you write x = y you aren't modifying either of the arrays, you're just making your local variable x refer to the same array as y.
If you want to swap the array contents, you have to modify the arrays themselves:
function swap(x,y) {
var temp = x.slice(0);
x.length = 0;
[].push.apply( x, y );
y.length = 0;
[].push.apply( y, temp );
}
Feb 2022 Solution to Swap 2 Entire Array Contents.
You can use destructuring to swap the 2 arrays:
let a = [ 1, 2, 3, 4 ];
let b = ['a','b','c','d'];
[a,b] = [b,a]; // swap
console.log(a); // ["a", "b", "c", "d"]
console.log(b); // [1, 2, 3, 4, 5]
let a = [ 1, 2, 3, 4 ];
let b = ['a','b','c','d'];
[a,b] = [b,a]; // swap
console.log(a); // ["a", "b", "c", "d"]
console.log(b); // [1, 2, 3, 4, 5]
To swap 2 arrays you may use
Version 1
let arrA = [1,2,3,4];
let arrB = ['Eve', 'Bar', 'Foo'];
let tempArr = [arrA, arrB]; // constructing new array
arrA = tempArr [1];
arrB = tempArr [0];
Version 1 (shorthanded)
let arrA = [1,2,3,4];
let arrB = ['Eve', 'Bar', 'Foo'];
// RHS : construction a new array
// LHS : destruction of array
[arrB, arrA ] = [arrA, arrB];
Version 2 (spread operator)
let arrA = [1,2,3,4];
let arrB = ['Eve', 'Bar', 'Foo'];
let arrC = [...arrB]
arrB = [...arrA]
arrA = [...arrC]