2

I'm toying around with Javascript and I now want to extract all pairs of consecutive characters from a string. So if the string is "test" I want to output "te", "es" and "st". Now I found out how to extract single letters from a string, by treating the string as an array, and using the "in" keyword as follows:

  var str = 'this is a test';
  //report letters
  for (var t in str) {
    var c = str[t];
    console.log(t + ': ' + c);
  }

This seems to work. The console logs suggest that t is an index. So I figure I should be able to use t + 1 as the index for the next character in str. However, my guesses don't seem to work, when trying the following:

  //report letterpairs
  for (var t in str) {
    var c = str[t] + str[t + 1];
    console.log(t + ': ' + c);
  }

This reports str[t + 1] as being "undefined".

  //report letterpairs
  for (var t in str) {
    var c = str.substring(t, t + 1);
    console.log(t + ': ' + c);
  }

This returns the first character when t = 0; but a much longer substring when t = 1, and the t-th up to the last character when t >= 2.

Now I assume I can probably use a "normal" for loop using for (t = 0; t < str.length; t += 1) { }

but firstly I prefer the cleanness of the "in" keyword and want to learn how to use the "in" keyword because I'm not familiar with it from other languages. And secondly, I'd like to know why the methods above using the "in" keyword do not work. Where's the error in my line of thought?

Erik Leppen
  • 325
  • 1
  • 2
  • 8

3 Answers3

1

That's not a good use-case for JavaScript's for...in loop. That loop type actually loops over the keys of an object. Because all keys in JavaScript are strings, t is always a string. Thus, t + 1 is also a string - and the + is string concatenation, not a sum.

What you really want to do is a normal for loop, counting indexes (this also lets you stop early so you don't try to get the last character and the character after it):

for(var i = 0;i < str.length - 1;i++) {
    var c = str[i] + str[i+1];
    console.log(t + ": " + c);
}

For Arrays and Strings you should stick with the normal for loop, not for...in.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Aaron Dufour
  • 17,288
  • 1
  • 47
  • 69
  • Hmm. t being a string explains a lot... And using whatever works is my way of learning stuff, good to know it's not advised. I'll switch to the for loop I'm used to. Thanks! :) – Erik Leppen May 18 '14 at 15:54
  • @ErikLeppen Glad my explanation helped. I just noticed that I messed up the code formatting, so its a lot more readable now. – Aaron Dufour May 18 '14 at 16:13
0

The problem is that t is a string, so t + 1 is also a string. The method substring then behaves in a different way than the one you expect when t + 1 is given. If you put str.substring(parseInt(t), parseInt(t) + 2); it gives a result similar to the one you expect (there are better ways to do this). The difference is that the last one is 3: t as there are no more characters.

I would prefer to use the for(var t = 0; t < str.length - 1; t++) in this case.

Ivaylo Petrov
  • 1,162
  • 9
  • 18
0

For-in in javascript is a bit special, it enumerates the attributes of an object and might give some unexpected results.

Have a look at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in

One of the problems you encounter is your indexer is going out of bounds because of the x+1 (in the last loop cycle you go outside of the array).

For arrays you better stick with a regular for-loop, or you could use some nice array helper methods offered by some of the frameworks (jQuery for instance).

Yvo
  • 18,681
  • 11
  • 71
  • 90