How does "for in" loop work in Javascript? - javascript

The program is as follows,
function sum(x) {
console.log(typeof x[0]); //return Number
var s=0;
for(var e in x) {
console.log(typeof e); //This return string
s+=e;
}
return s;
}
console.log(sum([1,2,3,4,5])); //return 001234
If I use a number constructor then it works fine.
function sum(x) {
console.log(typeof x[0]); // return Number
var s=0;
for(var e in x) {
s+=Number(e);
}
return s;
}
console.log(sum([1,2,3])); //return 6
What is happening at for in loop?

From MDN:
The for...in statement iterates over the enumerable properties of an object, in original insertion order.
and
A different property name is assigned to variable on each iteration.
Property names are strings. So you get strings. The + operator will concatenate strings.
If you convert the value to a number, then you don't have strings any more. The + operator will perform addition on numbers.
console.log(sum([1,2,3]); //return 6
No.
It throws an error because you have one ) too few. If you fix that, it outputs 3 because you are looping over the property names not the values, so you are adding 0, 1 and 2.

For ... in loop in es6 is used to loop over objects.
As an array is technically an object it loops over the index of the array. You can see this by console.logging inside the for loop.
Use For ... of loop to loop over arrays normally.
function sum(x) {
console.log(typeof x[0]); //return Number
var s=0;
for(var e of x) { // of loop
console.log(e)
s+=e;
}
return s;
}
console.log(sum([1,2,3,4,5])); //return 001234

Others have already pointed out that for-in iterates over properties, not values. In the case of an array the properties are the indices.
function sum(x) {
var s=0;
for(var e in x) {
s+=e;
}
return s;
};
var array = [1,2,3,4,5];
array.b="z";
console.log(sum(array)); // prints 001234b
In the resulting 001234b string you have:
Leading "0": The initial value of s
Then "0" because first index is 0
Then "1", etc

Related

I have an issue with removing an object key with a for in loop

I'm using a for x in loop to check if a value is == to [] and if so remove the property using remove but it just does not seem to work.
const whosOnline = (a) => {
var obj = { online:[],
offline:[],
away:[] };
for(let i = 0; i < a.length; i++){
if(a[i].lastActivity > 10 && a[i].status == 'online'){obj.away.push(a[i].username)}
else if(a[i].status == 'offline'){obj.offline.push(a[i].username)}
else{obj.online.push(a[i].username)}
}
for(let x in obj){
console.log(obj[x])
if(obj[x] === []){delete obj[x]}}
return obj
}
you were close, however you also need to reference the array index for each object key value. Comments explaining this in the code below.
var obj = { online:[],
offline:[],
away:[] };
for(var x in obj){
if(!obj[x][0]){ // The 0 is the index inside the online array, next loop it will be the offline array and then the away array.
console.log('The array is empty');
// Do what you want to do now that it is empty
// This will continue to loop through and check the value of all the keys in the object.
}
}
console.log('done');
Good luck -
Mitch from
https://spangle.com.au
Using some debugging (simply testing if a console.log gets printed for instance) you find that your if-condition is never true.
This is because you test if an array equals a newly created empty array. This can never be the case, because objects are compared by object reference instead of value.
Instead you want to probably test to see if your array is empty by doing ‘if(obj[x].length===0)’ (or shorter: ‘if(!obj[x].length)’)

How to use 'in' keyword in Javascript

I have a question here. I know my code have plenty of problems and I need your help.
The problem is, To return an object which have numbers of repetition information of the string.
The given string is
var r = countFreq(["a", "b", "b", "c", "c", "c", "d"]);
and the result have to be
{"a":1, "b":2, "c":3, "d":1 }
by console.log(r);
All that I know is, key(properties) have to be element and value(value of property) have to be the number of repetition.
AND, I must use 'in' key world to solve this problem.
Like,
if('property' in 'object') {
//...
}else {
//...
}
(if there's no property initialize as 1, and if there's a same property, add 1 each time)
I really appreciate your help.
(This post may have grammatical errors. I really feel sorry about that...)
function countFreq(array) {
var i;
for(i=0; i<array.length; i++)
{
if(array[i] in array)
{
return i += 1;
}else
{
return i = 1;
}
console.log(array[i]+": "+i+", ");
}
}
var r = countFreq(["a","b","c","c","c","d"]);
console.log(r);
According to MDN - The 'in' operator returns true if the specified property is in the specified object or its prototype chain.
Prop is a string or symbol representing a property name or array index (non-symbols will be coerced to strings).
Object is to check if it (or its prototype chain) contains the property with specified name.
So in your case, it depends what your object is? if you object is an array, you need to use prop as properties of array. All index values up to length of array will return true.
MDN Example of arrays
var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
0 in trees // returns true
3 in trees // returns true
6 in trees // returns false
'bay' in trees // returns false (you must specify the
// index number, not the value at that index)
'length' in trees // returns true (length is an Array property)
Symbol.iterator in trees // returns true (arrays are iterable, works only in ES2015+)
I think you are misunderstanding the in operator. In can be used in 2 cases, as a boolean operator to check for the presence of an index in an array or to iterate over the indexes of an array with a for loop. You are using it to check for the presence of a value in an array directly, which you cannot do. Also you are returning from the function after each iteration so you will only ever get 1 or 0.
I presume you want something like the following:
countFreq(array) {
var results = { a: 0, b: 0, c: 0, d: 0 };
for (var index in array) {
results[array[index]] ++;
}
return results;
}
Now you can access each result with results[‘a’] for instance, after calling countFreq. I think you need to read up on return and loops in JavaScript.

Iterating over an array of functions

I have the following JavaScript code:
function f(){
}
var arrOfFuncs = [f, f, f, f];
for (var i in arrOfFuncs){
console.log(typeof i);
console.log(i);
}
When I run the script it prints:
string
0
string
1
...
string
3
Since I am iterating over an array of functions, isn't "typeof i" supposed to be "function" and i.toString() supposed to be "function f(){}"?
No. The for…in construct iterates over the keys of an object or array, not its values.
You can use a simple for loop:
for (var i = 0; i < arrOfFuncs.length; i++){
console.log(typeof arrOfFuncs[i]);
console.log(arrOfFuncs[i]);
}
Or modify your for…in loop like this:
for (var i in arrOfFuncs){
console.log(typeof arrOfFuncs[i]);
console.log(arrOfFuncs[i]);
}
Or you could use the forEach method (introduced in ECMAScript 5.1):
arrOfFuncs.forEach(function(f) {
console.log(typeof f);
console.log(f);
});
When you iterate over keys of an object with for(var in in ...) i will equal the key - in the case of an array you are getting the indices as well as properties of the array (0, 1, 2, length, etc) and the type of that index or property key might very well be a string.
You want to access the value of the array at that key, so you need to do arrOfFuncs[i] - that said, it is probably better to use either .forEach or some equivalent if you can or use
for (var i = 0, l = arrOfFuncs.length; i < l; i++) {
var value = arrayOfFuncs[i];
}
Because you avoid the risk of accessing properties on the array you don't intend to access.
in your code i is the key it's not value. so your code should be like this to get function type:
function f(){
}
var arrOfFuncs = [f, f, f, f];
for (var i in arrOfFuncs){
console.log(typeof arrOfFuncs[i]);
console.log(arrOfFuncs[i]);
}
When you use for..in you are running over keys and not over values.
Read about JavaScript for..in loops.
This code will do what you want:
function f(){
}
var arrOfFuncs = [f, f, f, f];
for (var i in arrOfFuncs){
console.log(typeof arrOfFuncs[i]);
console.log(i);
}
JSFIDDLE
in for in iteration over arrays, i doesn't represent the element, it represents the index.
the below code works:
var array = [function f(){}, function k(){}];
for (var i in array) {
console.log(array[i]); //function()
console.log(typeof array[i]); //function
}

Check if an array is inside an array

The title should explain my question.
I have an array:
a = [[1,2],[1,3],[1,4]];
How can I check if the array [1,2] is inside the array a?
That depends on the situation.
given
var a = [1,2], b = [1,3], c = [a,b];
We can check easily if a resides in c, if we have c to test on.
for(var i=0,d;d=c[i];i++) {
if(d === a) {
//a is inside c
}
}
or even simpler for browser that supports it (ie7 doesn't)
if(c.indexOf(a) != -1) {
//a is inside c
}
But if we only have a, and a is not a local variable and we wish to know if it exists inside any array, then we can't, since a is a reference to an object and we can't possibly know if a reference to it exists elsewhere outside our current scope.
if you have a reference, the you can use the == operator. else you have to write your own method to test values. something like this:
function someMethod(testArr, wanted){
for (i=0; i<testArr.length; i++){
if(array_diff(testArr[i], wanted).length==0 && array_diff(wanted, $subArr).length==0){
return true;
}
}
return false;
}
function array_diff(a1, a2)
{
var a=[], diff=[];
for(var i=0;i<a1.length;i++)
a[a1[i]]=true;
for(var i=0;i<a2.length;i++)
if(a[a2[i]]) delete a[a2[i]];
else a[a2[i]]=true;
for(var k in a)
diff.push(k);
return diff;
}
If your array contains numbers or texts only, you can join each array into string, then compare if a string is inside the other.
var a = [[1,2],[1,3],[1,4]];
var b = [1,2]
var aStr = '#' + a.join('#') + '#'
var bStr = '#' + b.join() + '#'
if (aStr.indexOf(bStr) > -1){
alert ('b is inside a')
}else{
alert ('b is not inside a')
}
You can try this if your array elements are non-nested arrays.
return JSON.stringify([[1,2],[1,3],[1,4]]).indexOf(JSON.stringify([1,2])) > 0
This checks if the JSON representation of [1,2] is contained in the JSON representation of [[1,2],[1,3],[1,4]]
But in this case it gives a false positive
return JSON.stringify([[[1,2]],[1,3],[1,4]]).indexOf(JSON.stringify([1,2])) > 0
returns true.
You can also loop through the array object and for each of it's item you can use jQuery.isArray() to determine if the object is an array.

In Javascript, how do I check if an array has duplicate values?

Possible Duplicate:
Easiest way to find duplicate values in a javascript array
How do I check if an array has duplicate values?
If some elements in the array are the same, then return true. Otherwise, return false.
['hello','goodbye','hey'] //return false because no duplicates exist
['hello','goodbye','hello'] // return true because duplicates exist
Notice I don't care about finding the duplication, only want Boolean result whether arrays contains duplications.
If you have an ES2015 environment (as of this writing: io.js, IE11, Chrome, Firefox, WebKit nightly), then the following will work, and will be fast (viz. O(n)):
function hasDuplicates(array) {
return (new Set(array)).size !== array.length;
}
If you only need string values in the array, the following will work:
function hasDuplicates(array) {
var valuesSoFar = Object.create(null);
for (var i = 0; i < array.length; ++i) {
var value = array[i];
if (value in valuesSoFar) {
return true;
}
valuesSoFar[value] = true;
}
return false;
}
We use a "hash table" valuesSoFar whose keys are the values we've seen in the array so far. We do a lookup using in to see if that value has been spotted already; if so, we bail out of the loop and return true.
If you need a function that works for more than just string values, the following will work, but isn't as performant; it's O(n2) instead of O(n).
function hasDuplicates(array) {
var valuesSoFar = [];
for (var i = 0; i < array.length; ++i) {
var value = array[i];
if (valuesSoFar.indexOf(value) !== -1) {
return true;
}
valuesSoFar.push(value);
}
return false;
}
The difference is simply that we use an array instead of a hash table for valuesSoFar, since JavaScript "hash tables" (i.e. objects) only have string keys. This means we lose the O(1) lookup time of in, instead getting an O(n) lookup time of indexOf.
You could use SET to remove duplicates and compare, If you copy the array into a set it will remove any duplicates. Then simply compare the length of the array to the size of the set.
function hasDuplicates(a) {
const noDups = new Set(a);
return a.length !== noDups.size;
}
One line solutions with ES6
const arr1 = ['hello','goodbye','hey']
const arr2 = ['hello','goodbye','hello']
const hasDuplicates = (arr) => arr.length !== new Set(arr).size;
console.log(hasDuplicates(arr1)) //return false because no duplicates exist
console.log(hasDuplicates(arr2)) //return true because duplicates exist
const s1 = ['hello','goodbye','hey'].some((e, i, arr) => arr.indexOf(e) !== i)
const s2 = ['hello','goodbye','hello'].some((e, i, arr) => arr.indexOf(e) !== i);
console.log(s1) //return false because no duplicates exist
console.log(s2) //return true because duplicates exist
Another approach (also for object/array elements within the array1) could be2:
function chkDuplicates(arr,justCheck){
var len = arr.length, tmp = {}, arrtmp = arr.slice(), dupes = [];
arrtmp.sort();
while(len--){
var val = arrtmp[len];
if (/nul|nan|infini/i.test(String(val))){
val = String(val);
}
if (tmp[JSON.stringify(val)]){
if (justCheck) {return true;}
dupes.push(val);
}
tmp[JSON.stringify(val)] = true;
}
return justCheck ? false : dupes.length ? dupes : null;
}
//usages
chkDuplicates([1,2,3,4,5],true); //=> false
chkDuplicates([1,2,3,4,5,9,10,5,1,2],true); //=> true
chkDuplicates([{a:1,b:2},1,2,3,4,{a:1,b:2},[1,2,3]],true); //=> true
chkDuplicates([null,1,2,3,4,{a:1,b:2},NaN],true); //=> false
chkDuplicates([1,2,3,4,5,1,2]); //=> [1,2]
chkDuplicates([1,2,3,4,5]); //=> null
See also...
1 needs a browser that supports JSON, or a JSON library if not.
2 edit: function can now be used for simple check or to return an array of duplicate values
You can take benefit of indexOf and lastIndexOf. if both indexes are not same, you have duplicate.
function containsDuplicates(a) {
for (let i = 0; i < a.length; i++) {
if (a.indexOf(a[i]) !== a.lastIndexOf(a[i])) {
return true
}
}
return false
}
If you are dealing with simple values, you can use array.some() and indexOf()
for example let's say vals is ["b", "a", "a", "c"]
const allUnique = !vals.some((v, i) => vals.indexOf(v) < i);
some() will return true if any expression returns true. Here we'll iterate values (from the index 0) and call the indexOf() that will return the index of the first occurrence of given item (or -1 if not in the array). If its id is smaller that the current one, there must be at least one same value before it. thus iteration 3 will return true as "a" (at index 2) is first found at index 1.
is just simple, you can use the Array.prototype.every function
function isUnique(arr) {
const isAllUniqueItems = input.every((value, index, arr) => {
return arr.indexOf(value) === index; //check if any duplicate value is in other index
});
return isAllUniqueItems;
}
One nice thing about solutions that use Set is O(1) performance on looking up existing items in a list, rather than having to loop back over it.
One nice thing about solutions that use Some is short-circuiting when the duplicate is found early, so you don't have to continue evaluating the rest of the array when the condition is already met.
One solution that combines both is to incrementally build a set, early terminate if the current element exists in the set, otherwise add it and move on to the next element.
const hasDuplicates = (arr) => {
let set = new Set()
return arr.some(el => {
if (set.has(el)) return true
set.add(el)
})
}
hasDuplicates(["a","b","b"]) // true
hasDuplicates(["a","b","c"]) // false
According to JSBench.me, should preform pretty well for the varried use cases. The set size approach is fastest with no dupes, and checking some + indexOf is fatest with a very early dupe, but this solution performs well in both scenarios, making it a good all-around implementation.
function hasAllUniqueChars( s ){
for(let c=0; c<s.length; c++){
for(let d=c+1; d<s.length; d++){
if((s[c]==s[d])){
return false;
}
}
}
return true;
}

Categories

Resources