This question already has answers here:
What is the difference between ( for... in ) and ( for... of ) statements?
(18 answers)
Closed 2 years ago.
Could someone explain me why it prints [ '01', '11', '21' ]. I'm normally a java - Python - PHP dev
function g(element){
return element + 1;
}
function f(points, g){
let newArray = [];
for(let point in points){
newArray.push(g(point));
}
return newArray;
}
let array = [1, 2, 3];
console.log(f(array, g));
Yes, this is a javascript weirdness.
At first, the for in loop will iterate over the indizes, not the content of the array. This is "0", "1", "2".
The indizes do also seem to be interpreted as strings.
"0"+1=01
"1"+1=11
"2"+1=21
You are looping of the Keys by using in keyword in your for statement, To loop over array items use of keyword.
So your loop will be like this:
for(let point of points){
newArray.push(g(point));
}
The output looks as if the input array was ["0","1","2"] and not [1,2,3].
The mistake here is that the syntax for..in in javascript is used to loop through the keys/indexes of an object/array, not its values.
Something to notice here (which I did't know before and checked) is that the indexes of the array are converted to string when using a for..in, that's why the numbers were concatenated rather than summed.
Anyway, one correct syntax to loop through the elements of an array is the for..of syntax, which is used just like the for..in syntax and behaves as you expected.
Related
This question already has answers here:
Why can't I use Array#includes for a nested array?
(5 answers)
How to compare arrays in JavaScript?
(61 answers)
Closed 3 months ago.
TL;DR: the JavaScript code below returns false where I'm expecting a true, what's the best workaround?
console.log([['a']].includes(['a']))
I'm pushing arrays into arrays (to work with google sheets ranges in apps script, but the behaviour is the same in regular JavaScript).
I'd like to check if my parent array (let's call it [['a']]) contains specific child array (such as ['a']).
Unfortunately array.includes() doesn't seem to work as expected when the parameter is an array. (the code above returns false when it should be true as far as I know)
Am I missing anything? What do you think would be the best workaround?
The problem is array comparison.
console.log(['a'] == ['a']); //false
As the .includes() method loops through the array on which it is being called, it checks each element to see if it is equal to the value being tested for, until it finds a match, or checks every element of the array. As you can see above, when the value being tested is an array, it will not work.
A work around would be to write your own .includes() function in which you loop through all the child arrays in the parent array, and for each child array, loop through every element, testing whether it is equal to the corresponding element in the test array. You can use the .every() method for this.
let array = [['a']];
function includesArray(parentArray, testArray) {
for (let i = 0; i < parentArray.length; i++) {
if (parentArray[i].every(function(value, index) { return value === testArray[index]})) {
return true;
}
}
return false;
}
console.log(includesArray(array, ['a'])); //true
console.log(includesArray(array, ['b'])); //false
One quick alternative is to compare the JSON strigified arrays instead of comparing arrays directly.
console.log([['a']].map(x => JSON.stringify(x)).includes(JSON.stringify(['a'])))
This question already has answers here:
Destructuring to get the last element of an array in es6
(17 answers)
Closed 5 years ago.
I just discovered the delightful ES6 destructuring syntax for lists, i.e.
ls = [1, 2, 3]
[first, ...rest] = ls
which sets first to 1 and rest to [2,3]. However, is it possible to split the list into rest=[1,2] and last=3 using similar syntax?
I didn't have any luck googling it. I tried some obvious guesses for such a syntax (see below), but they all produced syntax errors.
[rest..., last] = ls
[...rest, last] = ls
I suppose I could do it by reversing the list twice, so an alternate solution to my question would be a constant time list reversal function.
What is commonly called "array destructuring" is actually destructuring an iterable, of which an array is a special case. The thing about iterables is that they can be infinite, or "lazy". That is the reason that you cannot destructure into some arbitrary number of elements followed by the last one:
const [...first, last] = integers();
because integers could be
function* integers() {
let n = 0;
while (true) yield n++;
}
and then what would last be?
No, this only works on trailing array elements. So, as you said, they way to achieve what you want would be reversing the array first.
Just in case you haven't come across a similar pattern for object, there is one:
const {a, ...rest} = {a: "prop1", b: "prop2", c: "prop3"}
A great tool to try all this new features out is https://babeljs.io/repl
This question already has answers here:
Why is using "for...in" for array iteration a bad idea?
(28 answers)
JavaScript: Why does the "for in" loop pick variables from __proto__?
(4 answers)
Loop through an array in JavaScript
(46 answers)
Loop (for each) over an array in JavaScript
(40 answers)
Closed 8 months ago.
The code which worked before was failing now in for loop after I added enyo.js. I suspect that when I use for(var ls in list) it loops through even when length is 0. When I put the debugged I found out that it is considering "findIndex" as one of value in list and goes into the loop. I have several places using for with in, I want to find out a best way to filter out "findIndex" or any invalid indexes so that only valid elements go into the loop
for(var ls in list)
{
var lin = list[ls].rb ;
}
If you list is an array, just use a regular for loop. It's generally not a great idea to use for...in with an array for exactly this reason and also because the order isn't guaranteed.
If you must use for...in use a hasOwnProperty check:
for (var ls in list)
{
if (list.hasOwnProperty(ls)) {
var lin = list[ls].rb;
// ...
}
}
Of course, if you only concern is whether you have an rb property, you could just test for that:
if (list[ls].rb) {
var lin = list[ls].rb;
}
Or even:
var lin = list[ls].rb;
if (lin) {
// do whatever you needed to do with lin
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Sorting a JavaScript object
Sort JavaScript object by key
I have array:
var arr = {}
arr[2323] = 1
arr[123] = 1
...
arr[n+232323] = 1
How to get all element of aobject sorted by key ( number order ? )
for ( key in arr ) {
alert(typeof(key))
}
return string type.
This is not an assosiative array, this is an object. There are no associative arrays in javascript.
Additionally, objects are not ordered. The order of keys in an object is meaningless.
Assuming there's some reason you don't use an Array in the first place, you can get an Array of the enumerable object properties, and sort that Array...
var sorted = Object.keys(my_obj)
.sort(function(a,b) {
return a - b;
});
This assumes the keys are numeric.
Then you can iterate the Array, and use each key to get the value from my_obj...
sorted.forEach(function(key) {
console.log(my_obj[key]);
});
Short answer: You can't.
Long answer: Associative Arrays in JavaScript are really JavaScript objects. When you add a new element, you're really adding a new member to the object. While most browsers will enumerate those members in the order they were added, the standard states that the order is undefined. You can't sort something that is undefined.
JavaScript objects (maps/dictionaries/associative arrays) have no order, you can't sort them. You will need to convert it to an array first. As you only need the keys of your object in your loop, the Object.keys() function (potentionally needs a shim for older browsers) is destined for the task:
var obj = {...};
var keys = Object.keys(obj).sort(function(a,b){return a-b;}); // numerically sorted
for (var i=0; i<keys.length; i++) {
alert(keys[i]);
// access the values by obj[keys[i]]
}
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
JavaScript “For …in” with Arrays
I'm trying to use the for-in syntax to loop through an array of numbers. Problem is, those numbers are getting converted to strings.
for(var element in [0]) {
document.write(typeof(element)); // outputs "string"
}
Is this standard behavior? I can think of a bunch of ways to work around it, but I'm really just looking for an explaination, to expand my understanding of JavaScript.
I think you misunderstand what JavaScript for...in does. It does not iterate over the array elements. It iterates over object properties. Objects in JavaScript are kind of like dictionaries or hashes in other languages, but keyed by strings. Arrays in particular are implemented as objects which have properties that are integers from 0 to N-1 - however, since all property names are strings, so are the indices, deep down.
Now let's take a bit different example than [0], since here index coincides with the value. Let's discuss [2] instead.
Thus, [2] is, if we ignore the stuff we inherit from Array, pretty much the same as { "0": 2 }.
for..in will iterate over property names, which will pick up the "0", not the 2.
Now, how to iterate over Arrays then, you ask? The usual way is:
var arrayLen = array.length;
for (var i = 0; i < arrayLen; i++) {
var el = array[i];
// ...
}
This is a repeat of Why is using "for...in" with array iteration a bad idea?
The for-in statement enumerates the properties of an object. In your case element is the name of the property and that is always a string.