Practising for..in loops

I am trying to learn the solution from this in regards to converting numbers input into Roman numerals.

(Referencing the second solution with 52 upvotes and uses both a for…in and while loop)

At the moment, I am struggling with applying for…in loops.

I have a problem to solve which is:

Given a string of words, you need to find the highest scoring word.

Each letter of a word scores points according to it’s position in the alphabet: a = 1, b = 2, c = 3 etc.

You need to return the highest scoring word as a string.

If two words score the same, return the word that appears earliest in the original string.

All letters will be lowercase and all inputs will be valid.

My attempt so far, is below:

function high(x){

var total=0;
var letterPts= {a:1, b:2 , c:3 , d:4 , e:5 ,f:6, g:7, h:8, i:9, j:10,
k:11, l:12, m:13 , n:14 , o:15, p:16, q:17 , r:18 , s:19 , t:20 , u:21,
v:22, w:23 , x:24 , y:25 , z:26 }

var lowerCaseX = x.toLowerCase();
for (letter in letterPts) {

I am confused on what to do next as the syntax for the for…in loop looks complex to me.

The idea is, if the input x = ‘‘example’’

e is 5 therefore total = 0 + 5 = 5
x is 24 therefore total = 5+24 = 29
a is 1 therefore total = 29 + 1 = 30
m is 13 therefore total = 30 + 13 = 43
p is 16 therefore total = 43 +16 = 59;
l is 12 therefore total = 59+12 = 71
e is 4 therefore total = 70 + 5 = 75

So ‘‘example’’ scores 75 points.

How can for… in be used to reflect the above logic?

Maybe a thing like

for (let letter in letterPts) {
// do something with letterPts[letter]
}

In this way with letterPts[letter] you can reference the points of that particular letter, but this is not the way I would go with it, it means iterating over all the 26 letters for each word, it may be unnecessary processing power but you can certainly do it with that

A for...in loop iterate over the keys of an object.

For now, I just need to learn how to apply for…in properly. Performance etc. is not the current issue… Could you please provide some example of for…in that looks through the keys of an object. I am struggling in understanding what exactly happens with each iteration. For instance, the link I gave to stackexchange which talks about converting roman numerials does it and I have no clue how to interpret it

This one?

function romanize(num) {
  var lookup = {M:1000,CM:900,D:500,CD:400,C:100,XC:90,L:50,XL:40,X:10,IX:9,V:5,IV:4,I:1},roman = '',i;
  for ( i in lookup ) {
    while ( num >= lookup[i] ) {
      roman += i;
      num -= lookup[i];
    }
  }
  return roman;
}

In that case you have the i that is first equal to "M" than to "CM" and so on (these are the various keys of the lookup object), so you have at the first iteration lookup["M"] (which is 1000) and then lookup["CM"] (which is 900) etc…

Knowing this do you get what the while loop is doing?

Yes that’s the one I want to understand by the end.

Do you have a simpler example that explains for…in loop? Thank you

the for...in loop iterates over the properties “in” an object or the indexes “in” an array and allows you to do stuff with them.

You know how you use the regular for loop to iterate over an array?

const arr = [5,4,3,2,1];

for (let i = 0; i < arr.length; i++) {
  console.log(i, arr[i]);
}

here is the same thing with the for...in loop:

const arr = [5,4,3,2,1];

for (let index in arr) { 
  console.log(index, arr[index]);
}

both of those will return:

0 5
1 4
2 3
3 2
4 1

A bonus to this approach is that you don’t need to know how long arr is. It will just iterate over from beginning to end for you–and it looks prettier.

Now where for...in comes into its own is with objects where you can’t really just use a regular for loop cause the properties aren’t going to be numbers that you can just use i for:

const obj = { "a": 1, "b": 2, "c": 3, "d": 4, "e": 5 };

for (let key in obj) {
  console.log(key, obj[key]);
}

This will result in:

a 1
b 2
c 3
d 4
e 5

Oh yeah! There is a catch: with for...in you are not guaranteed that the index/properties will be returned in any particular order. Personally, I haven’t seen it, say, return 3 2 0 1 4 instead of 0 1 2 3 4 when using it on arrays, but it could happen. So just be aware of that.

2 Likes

I think I’m done editing now. :smiley:

Thank you so much for such a detailed post.

Just clarifying, doing it by iteration’

''In iteration 1, key equals 1 hence, the first element in obj is chosen
In iteration 2, key equals 2 hence, the second element chosen is b… "
etc.

Is this understanding correct? Slightly tweaking your code to have a total value counter, check my understanding…

const obj = { "a": 1, "b": 2, "c": 3, "d": 4, "e": 5 };
var total = 0;

for (let key in obj) {
  console.log(key, obj[key]);
total = total + obj[key] ;
}

return total;

So in iteration 0, key is 0 therefore total = total + obj[0] = 0 + 1 = 1
in iteration 1 , key is 1 therefore total = total + obj[1] = 1 + 2 = 3
in iteration 2, key is 2 therefore total = total + obj[2] = 3 + 3 = 6
in iteration 3, key is 3 therefore total = total + obj[3] = 6 + 4 = 10
in iteration 4, key is 4 therefore total = total + obj[4] = 10 + 5 = 15

so return total would return 15

Is this correct or have I missed some details?

No. In this case, the key is referring to the letters (a, b, c, etc…) the letters here are the “keys” in key/value pairs. The value being the numbers in this case. So thus on the first iteration, the key is “a” and the value of obj["a"] is 1, so 0 + 1 is 1. The second time the key is “b” and the value of obj["b"] is 2 so 1 + 2 is 3, and so on up to the last iteration where the key is “e” and the value of obj[“e”] is 5 and thus 10 + 5 is 15.