How does for..of loop get values from Array - javascript

I have this piece of code,
let array = ["cj1rdd9fc00013f69ccln57g0", "cj1rdda8x00023f69g9281ay8"];
for (let [key, value] of array) {
console.log(key, value);
}
I expect, 0 cj1rdd9fc00013f69ccln57g0 and 1 cj1rdda8x00023f69g9281ay8 as the output. what am I missing here? How can I get the desired output?

Here is a bit of under the hood explanation.
for..of loop works on iterables. On each iteration it calls iterator.next().value to get values. Standard Array implementation has two kinds of iterators - the one that returns only values and the other that returns [key, value] pairs. If you need to get the second type of iterator, use array.entries().
let array = ["cj1rdd9fc00013f69ccln57g0", "cj1rdda8x00023f69g9281ay8"];
for (let [key, value] of array.entries()) {
console.log(key, value);
}
Here is the demo of two types of iterators:
var arr = ['a','b'];
var valueIterator = arr[Symbol.iterator]();
valueIterator.next().value; // returns a
valueIterator.next().value; // returns b
var arr = ['a','b'];
var valueKeyIterator = arr.entries();
valueKeyIterator.next().value; // returns [0, a]
valueKeyIterator.next().value; // returns [1, b]

Let try to understand whats happening here:
As per MDN-Docs, for..of provides value of each iteration to the assignment.
So when you do for(var v of array), v will hold value.
Now when you do let [key, value], you are using something thats called as Destructuring Assignment.
What it does is, for given list of variables, it will assign values at corresponding index value.
So, in let [a,b] = [10, 20], a=10 and b=20.
Coming back to your example,
let [key, value] of array,
is evaluated as let [key, value] = "cj1rdd9fc00013f69ccln57g0", so key holds value at 0th index, a.k.a c and value holds j.
How can I get the desired output
You can use other looping mechanisms like for, array.forEach etc.
There are other mechanisms like .map, .filter, .some, .every, .reduce but they have their own usecase, and can be suggested based on the processing logic.
Array.forEach
let array = ["cj1rdd9fc00013f69ccln57g0", "cj1rdda8x00023f69g9281ay8"];
array.forEach(function(value, index){
console.log(index, value)
})

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of
The way for of works is each time it will grab just the value, not the index.
let array = ["cj1rdd9fc00013f69ccln57g0", "cj1rdda8x00023f69g9281ay8"];
for (let item of array) {
console.log(item);
}
If you want to include the index, see this question:
How do you get the loop counter/index using a for-in syntax in JavaScript?

This is a destructuring assignment . This will work for es6 Maps and not for Arrays . For arrays you can just use a for of loop .

This Code, Console.log Array
let array = ["cj1rdd9fc00013f69ccln57g0", "cj1rdda8x00023f69g9281ay8"];
var i,j,tempstring;
for (i=0,j=array.length; i<j; i++) {
tempstring = array[i];
console.log(tempstring);
}

If you want to get the value and index of an array in every iteration using some fancy iteration, try this.
let array = ["cj1rdd9fc00013f69ccln57g0", "cj1rdda8x00023f69g9281ay8"];
array.map((value, index) => {
console.log(index, key);
});

Related

Inserting a new key-value pair to all objects in an array of objects without looping

I have an array of objects containing objects with similar structure. I need to add a new key value pair to all the objects in the array. How can I do it without looping the entire array.
Providing an example of the output that I require,
let arr = [{a:1,b:2}, {a:2,b:3}];
let key = c;
let value = 3;
Required output will be like,
//arr2 = [ {a:1,b:2,c:3}, {a:2,b:3,c:3}]
P.S: Tried using spread operator with little or no success.
How can I do it without looping the entire array.
You can't (reasonably). The completely unreasonable way would be to add it to Object.prototype, which is inherited by all objects, and thus would add it to all objects in the array — and everywhere else.
But again: You can't reasonably, you need to loop (in one form or another). That loop might be recursion a'la functional programming, but it's basically still a loop.
Here's the recursive technically-not-a-loop way:
let arr = [{a:1,b:2}, {a:2,b:3}];
let el = {c:3};
(function go(a, i, e) {
if (i < a.length) {
a[i].c = e.c;
go(a, i + 1, e);
}
})(arr, 0, el);
console.log(arr);
.as-console-wrapper {
max-height: 100% !important;
}
you can use map() operator on array and Object.assign() to append the key, value pair
let arr = [{a:1,b:2}, {a:2,b:3}];
let finalArray = arr.map(function(obj){return Object.assign(obj,{c:3});})
console.log(finalArray);

get key and value of array via underscore each

I would like to loop through an array and get the key and value of it. This is what I'm doing, but I don't get any output. What am I doing wrong?
let regexes = [];
regexes['some.thing'] = /([^.]+)[.\s]*/g;
_.each(regexes, function(regex, key) {
console.log(regex, key);
});
You are using array and adding a property to it which is not valid .Use object for it
let regexes = {};
regexes['some.thing'] = /([^.]+)[.\s]*/g;
_.each(regexes, function(regex, key) {
console.log(regex, key);
});
_.each iterates through the indices of the array. You are adding a non-numeric property to the array object. Your array is empty and _.each callback is not executed. It seems you want to use a regular object ({}) and not an array:
let regexes = {};
Now _.each should iterate through the object own (by using hasOwnProperty method) properties.
You are assigning a property to the array. Lodash is attempting to iterate through the numeric indices of the array, but there are none. Change the array to an object and Lodash will iterate through its enumerable properties:
let regexes = {};
regexes['some.thing'] = /([^.]+)[.\s]*/g;
_.forEach(regexes, function(regex, key) {
console.log(regex, key);
});
Alternatively, if using an array is necessary, simply push the value onto it:
let regexes = [];
regexes.push(/([^.]+)[.\s]*/g);
_.forEach(regexes, function(regex, i) {
console.log(regex, i);
});

Javascript Generic For Loop

Is there any way to create a generic for loop that will loop through either an array or an object correctly? I know I can write the following for loop, but it will also loop through other properties that would be added to an array.
for (item in x) {
console.log(item)
}
By this I mean a for loop that will iterate:
x = [1, 2]
x.foo = "foo"
y = {first:1, second: 2}
x as
1
2
y as
first
second
The reason behind this is that I won't know until runtime what x will be (either an Array or an Object). Is my only option to create a function that will check at runtime?
Use the for..of loop.
Iterating over arrays
const array = [1, 2];
array.foo = "test";
for (const number of array) {
console.log(number); // skips array.foo
}
Iterating over objects
const object = {
some: "string",
number: 42
};
for (const [key, value] of Object.entries(object)) {
console.log(key, value);
}
Anyway, from a code-style point of view, you should still check whether your object is an array before you iterate over it. You can use Array.isArray to achieve that. So, assuming data is either an object or an array:
if (Array.isArray(data)) {
for (const element of data) {
// Iterate over array
}
}
else {
for (const [key, value] of Object.entries(data)) {
// Iterate over object
}
}
Generic looping
Since in JavaScript, typeof [] === "object" (i. e. arrays are objects that use the element's index as its key), you could reduce it to a single loop with Object.entries:
for (const [key, value] of Object.entries(data)) {
// For arrays, `key` will be the index
}
Beware though that this latter method will not do justice to your exclusion of dynamic properties (e. g. array.foo), as you'll iterate over the result of Object.entries. If you do need to make this exclusion, use two for..of loops with Array.isArray as shown above.
If it's just the index/key values you need as per your expected output, here's a simple one-liner.
function loop(x) {
return (Array.isArray(x) ? x : Object.keys(x)).forEach(el => console.log(el));
}
loop(x); // 1 2
loop(y); // First Second
DEMO

Convert Object to 2D array in JavaScript

Can we convert an Object to a 2D Array,
My Object is like this
So That Array Key will be like 'STARS_2' and value is ["STARS_4", "STARS_0", "STARS_12"]
with My attempts I can get something like this,
With this Code,
var testArray =[];
_.map(childFieldNames, function (value, key) {
var newArray = new Array();
newArray[key] = value;
testArray.push(newArray);
});
Here Keys are actually another array, which I do not want. I want key should be like 'STARS_2' , i.e. property of master object.
Is this what you need?
var ary2D = Object.keys(childFieldNames).map(function (key) {
return childFieldNames[key];
});
better version for what Shilly showed would be:
const arr2D = Object.values(childFieldNames);
Object.entries(obj)
E.g.
const objVariable = {name: "Ted", job: "Dentist"}
const 2dArray = Object.entries(objVariable)
console.log(2dArray) // will print [["name", "Ted"], ["job", "Dentist"]]
Object.entries is a static method that belongs to the Object class. As a parameter, it accepts an object and returns a two-dimensional array.
Read more about it here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
You don’t need to create your structure into 2D array to just iterate over each key and its respective value(which is an array). If you want to iterate over it you can do something like this.
const object = {
a: [1,2,3],
b: [2,3,5]
};
for (const [key, value] of Object.entries(object)) {
value.forEach(v=>{
console.log(`${key}: ${v}`);
})
}

Get loop counter/index using for…of syntax in JavaScript

Caution:
question still applies to for…of loops.> Don't use for…in to iterate over an Array, use it to iterate
over the properties of an object. That said, this
I understand that the basic for…in syntax in JavaScript looks like this:
for (var obj in myArray) {
// ...
}
But how do I get the loop counter/index?
I know I could probably do something like:
var i = 0;
for (var obj in myArray) {
alert(i)
i++
}
Or even the good old:
for (var i = 0; i < myArray.length; i++) {
var obj = myArray[i]
alert(i)
}
But I would rather use the simpler for-in loop. I think they look better and make more sense.
Is there a simpler or more elegant way?
In Python it's easy:
for i, obj in enumerate(myArray):
print i
for…in iterates over property names, not values, and does so in an unspecified order (yes, even after ES6). You shouldn’t use it to iterate over arrays. For them, there’s ES5’s forEach method that passes both the value and the index to the function you give it:
var myArray = [123, 15, 187, 32];
myArray.forEach(function (value, i) {
console.log('%d: %s', i, value);
});
// Outputs:
// 0: 123
// 1: 15
// 2: 187
// 3: 32
Or ES6’s Array.prototype.entries, which now has support across current browser versions:
for (const [i, value] of myArray.entries()) {
console.log('%d: %s', i, value);
}
For iterables in general (where you would use a for…of loop rather than a for…in), there’s nothing built-in, however:
function* enumerate(iterable) {
let i = 0;
for (const x of iterable) {
yield [i, x];
i++;
}
}
for (const [i, obj] of enumerate(myArray)) {
console.log(i, obj);
}
demo
If you actually did mean for…in – enumerating properties – you would need an additional counter. Object.keys(obj).forEach could work, but it only includes own properties; for…in includes enumerable properties anywhere on the prototype chain.
In ES6, it is good to use a for... of loop.
You can get index in for... of like this
for (let [index, val] of array.entries()) {
// your code goes here
}
Note that Array.entries() returns an iterator, which is what allows it to work in the for-of loop; don't confuse this with Object.entries(), which returns an array of key-value pairs.
How about this
let numbers = [1,2,3,4,5]
numbers.forEach((number, index) => console.log(`${index}:${number}`))
Where array.forEach this method has an index parameter which is the index of the current element being processed in the array.
Solution for small array collections:
for (var obj in arr) {
var i = Object.keys(arr).indexOf(obj);
}
arr - ARRAY,
obj - KEY of current element,
i - COUNTER/INDEX
Notice: Method keys() is not available for IE version <9, you should use Polyfill code.
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
For-in-loops iterate over properties of an Object. Don't use them for Arrays, even if they sometimes work.
Object properties then have no index, they are all equal and not required to be run through in a determined order. If you want to count properties, you will have to set up the extra counter (as you did in your first example).
loop over an Array:
var a = [];
for (var i=0; i<a.length; i++) {
i // is the index
a[i] // is the item
}
loop over an Object:
var o = {};
for (var prop in o) {
prop // is the property name
o[prop] // is the property value - the item
}
As others have said, you shouldn't be using for..in to iterate over an array.
for ( var i = 0, len = myArray.length; i < len; i++ ) { ... }
If you want cleaner syntax, you could use forEach:
myArray.forEach( function ( val, i ) { ... } );
If you want to use this method, make sure that you include the ES5 shim to add support for older browsers.
Answer Given by rushUp Is correct but this will be more convenient
for (let [index, val] of array.entries() || []) {
// your code goes here
}
Here's a function eachWithIndex that works with anything iterable.
You could also write a similar function eachWithKey that works with objets using for...in.
// example generator (returns an iterator that can only be iterated once)
function* eachFromTo(start, end) { for (let i = start; i <= end; i++) yield i }
// convers an iterable to an array (potential infinite loop)
function eachToArray(iterable) {
const result = []
for (const val of iterable) result.push(val)
return result
}
// yields every value and index of an iterable (array, generator, ...)
function* eachWithIndex(iterable) {
const shared = new Array(2)
shared[1] = 0
for (shared[0] of iterable) {
yield shared
shared[1]++
}
}
console.log('iterate values and indexes from a generator')
for (const [val, i] of eachWithIndex(eachFromTo(10, 13))) console.log(val, i)
console.log('create an array')
const anArray = eachToArray(eachFromTo(10, 13))
console.log(anArray)
console.log('iterate values and indexes from an array')
for (const [val, i] of eachWithIndex(anArray)) console.log(val, i)
The good thing with generators is that they are lazy and can take another generator's result as an argument.
On top of the very good answers everyone posted I want to add that the most performant solution is the ES6 entries. It seems contraintuitive for many devs here, so I created this perf benchamrk.
It's ~6 times faster. Mainly because doesn't need to: a) access the array more than once and, b) cast the index.
That's my version of a composite iterator that yields an index and any passed generator function's value with an example of (slow) prime search:
const eachWithIndex = (iterable) => {
return {
*[Symbol.iterator]() {
let i = 0
for(let val of iteratable) {
i++
yield [i, val]
}
}
}
}
const isPrime = (n) => {
for (i = 2; i < Math.floor(Math.sqrt(n) + 1); i++) {
if (n % i == 0) {
return false
}
}
return true
}
let primes = {
*[Symbol.iterator]() {
let candidate = 2
while (true) {
if (isPrime(candidate)) yield candidate
candidate++
}
}
}
for (const [i, prime] of eachWithIndex(primes)) {
console.log(i, prime)
if (i === 100) break
}
To use for..of loop on array and retrieve index you can you use array1.indexOf(element) which will return the index value of an element in the loop. You can return both the index and the value using this method.
array1 = ['a', 'b', 'c']
for (element of array1) {
console.log(array1.indexOf(element), element) // 0 a 1 b 2 c
}
As mentionned in comments, this will return false index when the array contains non uniques values. (considering arr = ['a', 'b', 'c', 'a'], index of arr[3] will return 0 instead of 3)
// this loop is used in advanced javascript
//For Example I have an array:
let array = [1,2,3,4,5];
1) for(let key in array){
console.log(key);//this shows index of array {Result: 0,1,2,3,4}
console.log(array[key]);//this show values of array {Result: 1,2,3,4,5}
}
//Hopefully, You will quickly understand;

Categories

Resources