Variable in for loop is a string [duplicate] - javascript

This question already has answers here:
Why does javascript turn array indexes into strings when iterating?
(6 answers)
Is a JavaScript array index a string or an integer?
(5 answers)
Why is key a string in for ... in
(3 answers)
When iterating over values, why does typeof(value) return "string" when value is a number? JavaScript
(1 answer)
javascript for loop counter coming out as string [duplicate]
(3 answers)
Closed 6 years ago.
I'm not sure if this is normal behavior, but running this:
for (var i in [1, 2, 3]) {
console.log(i + 1);
}
Results in this:
// 01
// 11
// 21
Could somebody please explain, why is var i being treated like a string in this situation and not if I do for (var i = 0; i < [1, 2, 3].length; i++)?

Its most likely because in this for loop style (for..in), it is treating i as a key, and since keys in objects are usually strings (yes, an array is a type of object in javascript), it is treating it as a String.
parseInt(i) works in this situation, but for good programming practice, you would want to use a for loop that looks similar to this:
var array = [1, 2, 3];
for (var i = array.length - 1; i >= 0; i--) {
// do work with each array element here
}

The reason is that for .. in iterates object properties ("keys"), even for arrays. The "keys" in this case are the "indexes" of the array but it's still just object keys. As all object keys are strings, i gets a string value.

I think you want the values of the array, not the keys. If you can't use ES6, Xorifelse's answer works, but if you can, there is for ... of that works exactly as you probably thought:
for (let i of [1, 2, 3]) {
console.log(i + 1);
}
There is also Array.prototype.forEach in ES5 and up:
[1, 2, 3].forEach(function(value, index) {
console.log(value + 1);
});

Using the in keyword you're looping over each key in the object and those are string types and when using the + operator on a string will cause it to do a concatenation assignment.
If you want to perform an arithmetic assignment both the left and the right value of the operator have to be an integer type. A solution would be to try to parse the string to an integer:
console.log(parseInt("0") + 1); // 1
However... You should be looping over the value instead:
var data = [1, 2, 3];
for(var key in data){
console.log('a: data['+ key + '] = ' + data[key]);
}
for (var i = 0; i < data.length; i++) {
console.log('b: data['+ i + '] = ' + data[i]);
}
data.forEach(function(value, index){
console.log('c: data[' + index + '] = ' + value);
});
You could use the ES6 method to loop over the value alone:
for(let v of [1, 2, 3]) {
console.log(v);
}
The drawback of this method is the incompatibility of older android devices since its a somewhat new standard.
If you're using jQuery, you can also take a look at $.each as it allows for a key, value iteration in a nice one-liner that is compatible with older devices.
$.each([1, 2, 3], function(index, value) {
console.log( index + ": " + value );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

It's because i is a key/ index of every element, and it's string type.
So you are in fact concatenating string and int – the result is string.

That is because with the "in" keyword you traverse the keys of the object, not array indexes. However in this case, since the object is an array, the keys of the items in are indexes. And last, the keys in a for..in loop are strings.
So if you need numeric indexes of an array, you need to use a regular for loop.
var array = [0, 1, 2];
for (var i = 0; i < array.length; i++) {
console.log(i + 1);
}

Well when you use the for...in loop you're visiting each key from an object. Arrays are objects and their keys are numbers, but usually object keys are treated like strings.
If you want to convert the key to int, you can use parseInt function.
link!

for (var i in [1, 2, 3]) {
console.log(parseInt(i) + parseInt(1));
}

Related

Random commas appear in array ReactJS

I am trying to create this memory game in ReactJS and I have made an array in which I add 4 random numbers. Now everytime I press play game I need to fill the array with 4 random numbers 0 to 3 but I keep getting random commas that come out of nowhere in the array. I am quite new to React so any help is appreciated.
I have tried different methods of filling up the array but the commas still appear. P.S: keepArray was initialized just before the for loop.
for (let i = 0; i < 4; i++) {
let rand = Math.floor(Math.random() * 4)
keepArray = [...keepArray + rand]
console.log(keepArray)
}
Solution:
Replace:
keepArray = [...keepArray + rand]
with:
keepArray = [...keepArray, rand]
Explanation:
The spread operator (...) is literally "spreading" your array, that's why you need commas. The example bellow may help to visualize it:
// Let's start with a simple array:
var myArray = [1, 2, 3];
// Now, we add another element to it using spread:
var updatedArray = [...myArray, 4];
// Here, ...myArray is translated to [1, 2, 3]
// That means that the above could be read as:
var updatedArray = [1, 2, 3, 4];
Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
For an extra explanation about the "+" behavior, see Pavan Bahuguni answer.
The above answer does fix the problem, but the real reason for the behaviour is as follows.
The + operator is overloaded to serve the purposes of both number addition and string concatenation. When + receives an object (including array in your case) for either operand, it first calls the ToPrimitive abstract operation on the value, which then calls the [[DefaultValue]] algorithm with a context hint of number. Which intern calls toString method on the array.
var val = [1,2,3] + 1;
console.log(val); // "1,2,31"
And then you are trying to spread that string in an array like so,
var arr = [...val];
console.log(arr); // ["1", ",", "2", ",", "3", "1"]
this is the actual reason why you are seeing those commas.

Shorter way to remove an item by index from an array [duplicate]

This question already has answers here:
How to delete an item from state array?
(18 answers)
Closed 5 years ago.
I've made this post last year and today, I assume things can be simplified.
I need to remove an item from an array but by the index. When by the index, it does not matter if the array has same values. Your typical example:
let arr = [1,2,3,2,1] // just an array, not array with objects
let x = 1;
// This will not be an expected result:
// Find all values that is equal to 1 then remove
arr.filter(num => num !== x) //=> [2,3,2]
My expectation is when I remove the last element (1), for example, the array should be [1,2,3,2]:
let index = 4; // which is the last "1" in the array
let indexVal = arr.indexOf(4) // 1
let newArray = arr.splice(indexVal, 1) //=> [1,2,3,2]
Now, it's 2017, almost '18, is there a shorter way (es5/6) of doing this without any polyfil?
Edit:
Think of this as a todo:
<ul>
<li>me</li>
<li>me</li> // click to delete this one
<li>you</li>
<li>me</li>
</ul>
To correctly remove that item, I have to delete by the index not value
The Array.filter callback gives 2 arguments, number and index and you can filter the array this way.
let arr = [1,2,3,2,1]
let x = 4; //suppose you want to remove element at 4th index
let editedArray = arr.filter((num, index) => index !== x) //editedArray = [1,2,3,2]
EDIT:
The third parameter gives the whole array. Thanks #Oliver for pointing this out in comment
arr.splice(index, 1);
or if you specifically want to remove the last element:
arr.pop();
No indexOf call. The indexOf call never should have been there; it only ever looked like it worked because indexOf returns -1 for an element that isn't present, and splice treats negative indices as counting from the end of the array.
Also, splice modifies the array in place and returns an array of removed elements, so assigning its return value the way you were doing is misleading.
The only way I can think of is the one we use in Redux every day:
const arr = [1, 2, 3, 2, 1]
const index = 4 // index of the item you want to remove
const newArr = [...arr.slice(0, index), ...arr.slice(index + 1)]
console.log(newArr) // [1, 2, 3, 2]
It might not be the shortest but it is more 2017 and it is immutable, which is very important!
Ajay's answer might be what you're looking for. Anyway, there are people like me who prefer slightly-more-lines-but-more-readable/rewritable/maintable solution, I'd do it this way:
function removeElementByIndex(arr, x) {
var newArr = [];
for(var i = 0; i < arr.length; i++) {
if(i != x) {
newArr.push(arr[i]);
}
}
return newArr;
}
// Usage
removeElementByIndex([1, 2, 3, 2, 1], 4);// outputs: [1, 2, 3, 2]
Now, it's 2017, almost '18, is there a shorter way (es5/6) of doing
this without any polyfil?
LOL! Many basic things not yet implemented. We'll have to wait for 2118 or another programming language to replace JS (oh wait, there's one, aka jQuery :P ).

Get the highest but also unique number from an array

I have a question. I'm looking for a way to get the higest unique number of an array.
var temp = [1, 8, 8, 8, 4, 2, 7, 7];
Now I want to get the output 4 since that is the unique highest number.
Is there a good & hopefully short way to do that?
Yes, there is:
Math.max(...temp.filter(el => temp.indexOf(el) == temp.lastIndexOf(el)))
Explanation:
First, get the elements which are unique in the array using Array#filter
temp.filter(el => temp.indexOf(el) === temp.lastIndexOf(el)) // [1, 4, 2]
Now, get the max of the numbers from the array using ES6 spread operator
Math.max(...array) // 4
This code is equivalent to
Math.max.apply(Math, array);
If you don't want to get fancy, you can use a sort and loop to check the minimal number of items:
var max = 0;
var reject = 0;
// sort the array in ascending order
temp.sort(function(a,b){return a-b});
for (var i = temp.length - 1; i > 0; i--) {
// find the largest one without a duplicate by iterating backwards
if (temp[i-1] == temp[i] || temp[i] == reject){
reject = temp[i];
console.log(reject+" ");
}
else {
max = temp[i];
break;
}
}
Using the spread operator you can find the hightest number easily
Math.max(...numArray);
The only thing left then is to either filter duplicates from the array beforehand, or remove all the elements that match your maximum number if its a duplicate.
remove beforeHand would be easiest in es6 like this.
Math.max(...numArray.filter(function(value){ return numArray.indexOf(value) === numArray.lastIndexOf(numArray);}));
For a non es6 compatible way to remove duplicates have a look at Remove Duplicates from JavaScript Array, the second answer contains an extensive examinations of several alternatives

Duplicate an array an arbitrary number of times (javascript)

Let's say I'm given an array. The length of this array is 3, and has 3 elements:
var array = ['1','2','3'];
Eventually I will need to check if this array is equal to an array with the same elements, but just twice now. My new array is:
var newArray = ['1','2','3','1','2','3'];
I know I can use array.splice() to duplicate an array, but how can I duplicate it an unknown amount of times? Basically what I want is something that would have the effect of
var dupeArray = array*2;
const duplicateArr = (arr, times) =>
Array(times)
.fill([...arr])
.reduce((a, b) => a.concat(b));
This should work. It creates a new array with a size of how many times you want to duplicate it. It fills it with copies of the array. Then it uses reduce to join all the arrays into a single array.
The simplest solution is often the best one:
function replicate(arr, times) {
var al = arr.length,
rl = al*times,
res = new Array(rl);
for (var i=0; i<rl; i++)
res[i] = arr[i % al];
return res;
}
(or use nested loops such as #UsamaNorman).
However, if you want to be clever, you also can repeatedly concat the array to itself:
function replicate(arr, times) {
for (var parts = []; times > 0; times >>= 1) {
if (times & 1)
parts.push(arr);
arr = arr.concat(arr);
}
return Array.prototype.concat.apply([], parts);
}
Basic but worked for me.
var num = 2;
while(num>0){
array = array.concat(array);
num--}
Here's a fairly concise, non-recursive way of replicating an array an arbitrary number of times:
function replicateArray(array, n) {
// Create an array of size "n" with undefined values
var arrays = Array.apply(null, new Array(n));
// Replace each "undefined" with our array, resulting in an array of n copies of our array
arrays = arrays.map(function() { return array });
// Flatten our array of arrays
return [].concat.apply([], arrays);
}
console.log(replicateArray([1,2,3],4)); // output: [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
What's going on?
The first two lines use apply and map to create an array of "n" copies of your array.
The last line uses apply to flatten our recently generated array of arrays.
Seriously though, what's going on?
If you haven't used apply or map, the code might be confusing.
The first piece of magic sauce here is the use of apply() which makes it possible to either pass an array to a function as though it were a parameter list.
Apply uses three pieces of information: x.apply(y,z)
x is the function being called
y is the object that the function is being called on (if null, it uses global)
z is the parameter list
Put in terms of code, it translates to: y.x(z[0], z[1], z[2],...)
For example
var arrays = Array.apply(null, new Array(n));
is the same as writing
var arrays = Array(undefined,undefined,undefined,... /*Repeat N Times*/);
The second piece of magic is the use of map() which calls a function for each element of an array and creates a list of return values.
This uses two pieces of information: x.map(y)
x is an array
y is a function to be invoked on each element of the array
For example
var returnArray = [1,2,3].map(function(x) {return x + 1;});
would create the array [2,3,4]
In our case we passed in a function which always returns a static value (the array we want to duplicate) which means the result of this map is a list of n copies of our array.
You can do:
var array = ['1','2','3'];
function nplicate(times, array){
//Times = 2, then concat 1 time to duplicate. Times = 3, then concat 2 times for duplicate. Etc.
times = times -1;
var result = array;
while(times > 0){
result = result.concat(array);
times--;
}
return result;
}
console.log(nplicate(2,array));
You concat the same array n times.
Use concat function and some logic: http://www.w3schools.com/jsref/jsref_concat_array.asp
Keep it short and sweet
function repeat(a, n, r) {
return !n ? r : repeat(a, --n, (r||[]).concat(a));
}
console.log(repeat([1,2,3], 4)); // [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
http://jsfiddle.net/fLo3uubk/
if you are inside a loop you can verify the current loop index with the array length and then multiply it's content.
let arr = [1, 2, 3];
if(currentIndex > arr.length){
//if your using a loop, make sure to keep arr at a level that it won't reset each loop
arr.push(...arr);
}
Full Example:
https://jsfiddle.net/5k28yq0L/
I think you will have to write your own function, try this:
function dupArray(var n,var arr){
var newArr=[];
for(var j=0;j<n;j++)
for(var i=0;i<arr.length;i++){
newArr.push(arr[i]);
}
return newArr;
}
A rather crude solution for checking that it duplicates...
You could check for a variation of the length using modulus:
Then if it might be, loop over the contents and compare each value until done. If at any point it doesn't match before ending, then it either didn't repeat or stopped repeating before the end.
if (array2.length % array1.length == 0){
// It might be a dupe
for (var i in array2){
if (i != array1[array2.length % indexOf(i)]) { // Not Repeating }
}
}

Javascript Arrays - Find Duplicates [duplicate]

This question already has answers here:
Get all non-unique values (i.e.: duplicate/more than one occurrence) in an array
(97 answers)
Closed 8 years ago.
Here is my question...
Given an array populated with numbers as a function parameter, produce a resulting array which contains any duplicates number from the array.
For example, given the array [ 1, 2, 4, 4, 3, 3, 1, 5, 3 ] it should return [1, 4, 3]. For extra bonus points return a sorted array.
I am starting out with Javascript - I know the language however, using it in the correct way ( as one should ) I'm still getting to grips with.
My pseudo code for this would be to:
Create an array with the numbers above var numbers = [1, 2, 4, 4, 3, 3, 1, 5, 3];
Then create an empty array named "result" var result = [];
Create a for loop that goes through the var numbers to check for duplicates which will then populate the empty array "result" with the duplicates
for (var i = 0;i < numbers.length; i++) {
//This is where I'm stuck...
}
I'm not sure what to do within the for loop to populate the var result and to throw in to the mix... The given array has to be a function parameter which makes sense so you can change the numbers in one place.
Any feedback on my thought process on this so far is greatly appreciated but ultimately I am wanting to learn how to achieve this.
Here is a JSFiddle of my progress so far... http://jsfiddle.net/fbauW/
One way of doing this (and it's not the only way) is by checking for existing elements in the array. Take a look at JavaScript's lastIndexOf function:
http://www.w3schools.com/jsref/jsref_lastindexof_array.asp
It will return -1 if the object does not exist in your array, and if it exists, will return an index of a later position than you are in. So you can use an if statement in your loop that checks whether or not there is another index containing your number, and add it in to your results array IF AND ONLY IF the index you get back != the index you are currently on (if they equal, this means that there is only one of that element in the list).
If you need more help, comment here and I can type some code in!
Good luck!
Array.prototype.contains = function(k) {
for ( var p in this)
if (this[p] === k)
return true;
return false;
};
//this prototype function checks if an element is already in the array or not
//go through all the array and push the element to result if it is not
//this way we can eliminate duplicates
//result will contain the resultant array
function findDuplicates(Numbers) {
var arrayLength = Numbers.length, i, j, result = [];
for (i = 0; i < arrayLength; i++) {
for (j = 0; j < arrayLength; j++) {
if (a[i] == a[j] && i != j && !result.contains(a[i])) {
result.push(a[i]);
}
}
}
return result;
}

Categories

Resources