for in loop behaving strangely in javascript - javascript

var friends=['2','3'];
console.log(friends);
var rooms=[];
for(var friend in friends){
var room = 'userid'+friend+'friends';
console.log(room);
rooms.push(room);
}
console.log(rooms);
this outputs
[ '2', '3' ]
userid0friends
userid1friends
[ 'userid0friends', 'userid1friends' ]
3 is neglected entirely, and it behaves even more strangely on my node.js server

friend here is the index of your array, not the value at the index
var room = 'userid'+friends[friend]+'friends';
Plus when looping through an array I don't recommend to use for..in loops, you can use Array.prototype.map or plain for loop with the length of your array
Array map example:
var friends=['2','3'];
console.log(friends);
var rooms= friends.map(function (friend, index) {
return 'userid' + friend + 'friends';
});
console.log(rooms);
Plain for loop:
var friends=['2','3'];
console.log(friends);
var rooms=[];
for (var i = 0, l = friends.length; i < l; ++i) {
var room = 'userid' + friends[i] + 'friends';
console.log(room);
rooms.push(room);
}
console.log(rooms);

The for in structure is used to loop the object, for key in object, key is the property name of the object, when used for an array, key will be the array index.
You could use .map to get your result:
var friends=['2','3'];
var rooms = friends.map(function(e) {
return 'userid'+e+'friends';
});

A for in loop is used to enumerate objects. You are trying to iterate over an array. A better technique for iterating would be a regular for loop or the Array.forEach() method.
In a for in loop, the variable contains the key, not the value. To get the value, use the key:
for(var i in friends){
var friend = friends[i];
...
}
But, again, this enumerates an object, including any properties besides the array elements. This means that if any code adds a method to Array.prototype, that method will also be enumerated. Using .forEach() is better:
friends.forEach(function (friend, i) {
...
});
Better yet, since you are trying to create a new Array based on the contents of another, use Array.map(). That is exactly what it's for.
var rooms = friends.map(function (friend, i) {
return 'userid'+friend+'friends';
});

Related

How to send each player a list of players while excluding themselves from the list

Sorry for the confusing title.
If I have an array as ['Peter','James','Susan','Thomas'] and I want to get the array.length number of new arrays (in this case is 4), with each of the new array having one less different name of the original one.
So what I want is this 4 arrays:
['James','Susan','Thomas']
['Peter','Susan','Thomas']
['Peter','James','Thomas']
['Peter','James','Susan']
And if I want to sent each new array to person whose name is not there. (So I want to sent Peter ['James','Susan','Thomas'], and to James ['Peter','Susan','Thomas'].
My current code is:
for(var i=0;i<array.length;i++){
var player = array[i]
var newArray= array.splice(i,1)
io.to(player)emit('message', newArray)
}
The returned array only has one name in it.
The problem is that array.splice() modifies the original array. You need to make a copy of it first, so you don't destroy the original. You also shouldn't assign .splice to newArray, because it returns an array of the elements that were removed, not the modified array.
for (var i = 0; i < array.length; i++) {
var player = array[i];
var newArray = array.slice();
newArray.splice(i, 1);
io.to(player).emit('message', newArray);
}
Array#splice actually mutates the array it is called upon. The reason it can be confusing is that it also returns an array containing the elements you just deleted -- hence you receiving an array with a single item. Try using Array#forEach instead, and make a copy of your array using Array#slice before running splice so that the original array is not damaged with each iteration.
// For demo purposes
var io = { to: function(player) { return { emit: function(s, msg) { console.log(player, 'received', msg) } } } }
var array = ['Peter', 'James', 'Susan', 'Thomas']
array.forEach(function(player, i, a) {
(a = a.slice()).splice(i, 1)
io.to(player).emit('message', a)
})

Learning While Loops. Can't figure out what I am missing in my code.

Write a function called indexToString. This function should:
1. Take an array as an argument
2. Create and return a new array of all passed array elements as strings
3. Each strings should be formatted like so: “[index] is [element at index]”
This is the error I am getting: returns an array of passed-in array elements as strings with element index specified
expected undefined to deeply equal [ '0 is 1', '1 is 2', '2 is 3' ]
Here is my code:
var indexToString = function(array){
index = 0;
elementAtIndex = 0;
var i = 0;
while(i < array.length){
console.log(index + " is " + elementAtIndex);
i++
}
return array[i];
};
Two Three errors.
Firstly, the while loop will exit when i is no longer less than array.length; the first such number is array.length. This means, at the end of the loop, array[i] is array[array.length], which is just outside the array, thus undefined.
Secondly, you are supposed to return an array of strings, as told by your test failure message; not print them to the console.
EDIT: Thirdly, what Spencer said. :) Use i instead of index, and array[i] instead of elementAtIndex.
You want to start with an empty array outside the loop, and push each string you construct into it; then return that array after the loop.
Or you can do it with "new" JavaScript:
var indexToString = array => array.map((e, i) => `${i} is ${e}`)
You should reflect a bit more on your code, it is quite nonsense so far.
Let's decompose the question to identify what should be done:
Write a function called indexToString. This function should:
Take an array as an argument
Create and return a new array of all passed array elements as strings
Each strings should be formatted like so: “[index] is [element at index]”
So:
you create a function called indexToString which body contains the code, as you did.
In the initialization part before your while, you should create a new empty array that is going to be filled, and declare an integer called index for example initialized at 0 that is going to be used to loop through the original array. (Tip: var new_array = []; to create, and use new_array.push(elem); to append an element)
in your while, you should push at the end of your new array a string built as follow: "["+index+"] is ["+array[index]+"]" AND you should increment your index. You loop while(index < array.length).
At the end, you can return the new array !
Good luck with learning programming!
If the arraylenth is 10, the function will return array[10].This is an array-bound.
When you enter the last loop, the i becomes equal to array.length, so array[i] is undefined after this. But probably this is not what you wanted. you want to return the full array.
var indexToString = function(array){
var new_array = [];
var i = 0;
while(i < array.length){
new_array[i] = i + " is " + array[i];
i++;
}
return new_array;
};
console.log(indexToString([1,2,3]));

$.each() over Key value pair array

I've created my array as following:
var test = [];
test['pizza'] = 4;
test['pudding'] = 6;
I'm used to use $.each to loop over my array and print out the values and indexes. I'm doing this as following:
$.each(test, function (index, value){
console.log(value);
});
Yet somehow it does only print [].
How would one loop through an array as mine to print out the values 4 and 6?
each will only iterate over iterable properties of the array, pizza and pudding are not iterable properties.
As you require the key-value pair, declare the variable as object.
var test = {};
test['pizza'] = 4;
test['pudding'] = 6;
You don't need jQuery to iterate through a Javascript array, just use for.
var test = [];
test['pizza'] = 4;
test['pudding'] = 6;
for (var k in test) {
if (test.hasOwnProperty(k)) {
console.log('Key: ' + k + ' Value: ' + test[k]);
}
}
// Key: pizza Value: 4
// Key: pudding Value: 6
You don't need to declare test as an object for this (suggested in other answers), array is fine.
By using for you are improving performance of your application. See here.
In both Firefox and Chrome, the for loop is well over 100x faster than
the others.
you might want to choose what happens to serve your needs. I guess you were trying to get a array of objects which will look something like [{},{},{},{}]
Here test is an object(Associative array), not an array so you need to declare it as javascript object
var test = {};
test['pizza'] = 4;
test['pudding'] = 6;
$.each(test, function (index, value){
console.log(value);
});

forEach on array of undefined created by Array constructor

I am just wondering why it is not possible to make forEach on array of undefined.
Code:
var arr = new Array(5); // [undefined x 5]
//ES5 forEach
arr.forEach(function(elem, index, array) {
console.log(index);
});
//underscore each
_.each(arr, function(elem, index, array) {
console.log(index);
});
Both examples do not execute function.
Now to make foreach, I have to make:
var arr = [0,0,0,0,0];
Then make forEach on it.
I am trying to make an array with specified size and loop through it, avoiding for loop. I think that it is clearer using forEach than for loop.
With array with length 5 it is not a problem, but it would be ugly with bigger arrays.
Why there is a problem looping through array of undefined values ?
Array(5) is essentialy equivalent to
var arr = [];
arr.length = 5;
In javascript changing array's length doesn't set any values for it's numeric properties nor does it define those properties in the array object. So numeric properties are undefined instead of having undefined value. You can check it by using:
Object.keys(arr)
When iterating javascript iterates through numeric properties of the array, so if these don't exist, there is nothing to iterate over.
You can check it by doing:
var arr = Array(5)
//prints nothing
arr.forEach(function(elem, index, array) {
console.log(index);
});
arr[3] = 'hey'
//prints only 'hey' even though arr.length === 5
arr.forEach(function(elem, index, array) {
console.log(index);
});
The following code:
var arr = [undefined, undefined];
creates and array of length ===2 and sets the both numeric properties 0 and 1 to undefined.
Looking at a simplified implementation of .forEach() may help.
Array.prototype.my_for_each = function(callback, thisArg) {
for (var i = 0; i < this.length; i++) {
if (i in this) {
callback.call(thisArg, this[i], i, this);
}
}
};
So you can see that what happens is that the method does iterate the entire Array (according to the spec), but it only invokes the callback if the member actually exists. It checks by looking for the property (the index) using the in operator, which tests to see if the object either has or inherits the property.
If in shows that the index exists, the callback is invoked.
So given this Array:
var arr = ["foo", "bar", "baz"];
This will output all 3 items:
arr.my_for_each(function(item) {
console.log(item);
});
// "foo" "bar" "baz"
But if we use delete to remove a member, it leaves a hole in the Array, which will now get passed over.
delete arr[1];
arr.my_for_each(function(item) {
console.log(item);
});
// "foo" "baz"
When you created an Array using Array(5), it created one without any members, but with the .length set to 5. So this is an example of a sparse Array (very sparse in this instance). Because none of the indices will be found by in, the callback is never invoked.
You can use Array.from to create an array and pass lambda function that will be invoked on each item in the array.
detailed documentation
const arr = Array.from(
{ length: 5 },
() => 0
)
console.log(arr)
Other answers have explained the problem, but not provided solutions.
ES6 Spread syntax fills in sparse values with undefined. So does Array.apply(null, sparseArray), which has the benefit of working in older browsers, but takes a bit more work to understand.
const sparseArray = new Array(5);
const unsparseArray1 = Array.apply(null, sparseArray);
const unsparseArray2 = [...sparseArray];
function arrayApply() {
// ES5 forEach works with either approach
unsparseArray1.forEach(function(elem, index, array) {
console.log(index);
});
}
function es6Spread() {
// Lodash each works with either approach
_.each(unsparseArray2, function(elem, index, array) {
console.log(index);
});
}
<html><head>
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.21/lodash.min.js"></script>
<title>Making sparse arrays unsparse</title>
</head><body>
<p><button onclick="arrayApply();">Array.apply(null, sparseArray)</button></p>
<p><button onclick="es6Spread();">[...sparseArray]</button></p>
</body>
</html>
In my case, I was looking for an elegant solution to creating an array of digits starting with 0 to X.
In an elegant manner with arrow functions, it comes up with a 1 line of code
const arrayLength = 10;
const arrayOfDigits = Array.apply(null, Array(arrayLength)).map((_, index) => index);
Appeared to me quite a sophisticated one, much more than a separate block of code with a for cycle.

JavaScript Array

I usually script/program using python but have recently begun programming with JavaScript and have run into some problems while working with arrays.
In python, when I create an array and use for x in y I get this:
myarray = [5,4,3,2,1]
for x in myarray:
print x
and I get the expected output of:
5
4
3
..n
But my problem is that when using Javascript I get a different and completely unexpected (to me) result:
var world = [5,4,3,2,1]
for (var num in world) {
alert(num);
}
and I get the result:
0
1
2
..n
How can I get JavaScript to output num as the value in the array like python and why is this happening?
JavaScript and Python are different, and you do things in different ways between them.
In JavaScript, you really should (almost) always iterate over an array with a numeric index:
for (var i = 0; i < array.length; ++i)
alert(array[i]);
The "for ... in" construct in JavaScript gives you the keys of the object, not the values. It's tricky to use on an array because it operates on the array as an object, treating it no differently than any other sort of object. Thus, if the array object has additional properties — which is completely "legal" and not uncommon — your loop will pick those up in addition to the indexes of the "normal" array contents.
The variable num contains the array item's index, not the value. So you'd want:
alert(world[num])
to retrieve the value
The for var in... loop in JavaScript puts the keys in the variable instead of the actual value. So when using for var ... you should do something like this:
var world = [5, 4, 3, 2, 1];
for ( var key in world ) {
var value = world[key];
alert(key + " = " + value);
}
And note that this way of looping is best used when you're using objects instead of arrays. For arrays use the common:
for ( var i = 0, j = arr.length; i < j; i++ ) { ... }
Or if you're targeting modern browser you can use the forEach-method of arrays:
var arr = [1, 2, 3];
arr.forEach(function(num) {
alert(num);
});
The for...in loop loops over all key elements; not the values.
I would recommend you to use
for(var i=0; i<arr.length; i++){
alert(arr[i]);
}
When you use the in operator num becomes a key. So simply use this key to get a value out of the array.
var world = [5,4,3,2,1]
for (var num in world) {
alert(world[num]);
}
try this.
var world = [5,4,3,2,1]
for(var i=0;i<world.length;i++){
alert(world[i])
}
Because javascript in your case is printing the index of the element, not the value.
the result you got is just element index,if you want to get element value
your code should like this
var world = [5,4,3,2,1]
for (var num in world) {
alert(world[num]);
}
The for in iteration in JavaScript works only for the object data type. The way it works is that it lets you iterate over the attributes of an object. arrays are objects in JavaScript, but the for in only works on its attributes, not the array values.
For example you might define an array as such:
var arr = [1,2,3];
And you can assign attributes to this array, because it's actually an object:
arr.foo = "bar";
arr["1"] = 2;
Now when you use the for in iteration method you will be able to iterate over the attributes we just assigned above;
for(var i in arr) console.log(i);
To iterate over the actual array values you need to use the for(var i=0; i<arr.length; i++) construct.
Hope this helps.
In javascript it's advised to loop Arrays different from looping Objects. You are using an object loop, which may return unexpected result (for instance if the Array.prototype was extended with custom methods you would iterate those too, and it does't guarantee the order of the array is preserved). There are many ways to loop through an array, using it's index:
// regular
var arr = [1,2,3,4,5]
,i
;
for (i=0;i<arr.length;i++) {
console.log(arr[i]);
}
// using while
var arr = [1,2,3,4,5]
,i = 0
;
while ((i = i + 1)<arr.length) {
console.log(arr[i]);
}
// using while reversed
var arr = [1,2,3,4,5]
,i = arr.length
;
while ((i = i - 1) > -1) {
console.log(arr[i]);
}
Note: Why not use i++ or i--? To avoid confusion, index out of range-errors and to satisfy JSLint

Categories