traverse a string char by char javascript
Asked Answered
T

3

9
function SimpleSymbols(str) { 
    var letter =['a','b','c','d','e','f','g','h','i','j',
    'k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];

    var newstr = "";
    for (var i = 0; i<str.length; i++){
        if (str.charAt(i).toLowerCase() in letter){
            newstr += "M";
        }
        else{
            newstr += "X";
        }
    }

return newstr; 

}

If str is "Argument goes here" it returns XXXXXXXXX. WHy doesn't it return MMMMMMMMMM?

Trueman answered 25/8, 2014 at 16:9 Comment(0)
P
10

you do not look up an entry in an array with in. use indexOf() to find the position of an array entry. indexOf() will return the position or -1 if no entry is found.

for (var i = 0; i<str.length; i++){
    var strChar = str.charAt(i).toLowerCase();

    if ( letter.indexOf(strChar) >= 0 ) {
        newstr += "M";
    }
…
Piscator answered 25/8, 2014 at 16:12 Comment(4)
And if you could explain your answer now?Anasarca
@FelixKling var why? what do you mean?Piscator
That's exactly what I was thinking when you just posted the code.Chirp
does it make sense to you now?Piscator
C
4

The in operator returns true if the object has a property with that name, not with that value.

An array is basically an object with numeric properties. I.e. the indexes are the property names of the object. It basically looks like this:

var letters = {
  0: 'a',
  1: 'b',
  ...
  length: ...
};

So in your case the condition will only be true if str.charAt(i).toLowerCase() returns a number between 0 and letter.length (and since charAt only returns one character, it can only be 0-9).

Example:

> var letters = ['a', 'b', 'c'];
> 'a' in letters // array doesn't have a property 'a'
false
> 0 in letters   // array has a property 0 (it's the first element)
true

So since, "Argument goes here" doesn't contain any digits, the in condition will always be false and that's why you get XXXXXX... as result.

See the question "How do I check if an array includes an object in JavaScript?" for testing the existence of an element in an array.


FWIW, to make the in operator work, you would have to create an object of the form:

var letters = {
  'a': true,
  'b': true,
  // ...
};

but that's a bit cumbersome to write.

Chirp answered 25/8, 2014 at 16:15 Comment(9)
so I should use .contains?Trueman
there is no contains.Piscator
@dreamlab: I never said there is.Chirp
i know you didn't. but @mikeandike didn't understand.Piscator
Btw, downvoter, if anything is wrong with my answer, let me know, I'm happy to correct it.Chirp
Nothing worth of a down vote far as I can see. What do you think @dreamlab?Opinionated
in depth explanation of the topic. only thing i would suggest to edit is the "array.contains" title so that @mikeandike's assumption can not be made.Piscator
@dreamlab: That's the title of the other question. I simply copied the link, it gets autoconverted by the parser. But I can make it clearer that this is a link to a question.Chirp
oh, i see. than the title is bad. maybe just link without the title ;)Piscator
S
0

Allow me to offer a side view, another way handle what I think you intent to do by using Regular Expressions with something like:

"test2".replace(/[a-z]/gi,"M").replace(/[^M]/g,"X") //Outputs "MMMMX"

String.replace will replace an string that contains letters from [a-z] the i at the end of the expression means case insensitive. g means will search for all possible matches and not just the first match. In the second expression [^M] this ^ means negation so anything that is not an M will be replaced with X.

There is another way in which we implement a custom function within the String.replace using Regular Expressions and it can be implemented like this:

"test2".replace(/([a-z])|([^a-z])/gi,
     function(m,g1, g2){ 
            return g1 ? "M" : "X";  
     });

In regular expression parenthesis creates groups and | means or in this expression ([a-z])|([^a-z]) there 2 groups one with letters from a-z and the other which means everything that is not a-z with the replace function we asked only for group g1 if it is group 1 is M otherwise is an X.

Another cool thing you could do is add this function to all your string by prototyping it like:

String.prototype.traverse = function(){ return this.replace(/([a-z])|([^a-z])/gi,function(m,g1){ return g1 ? "M" : "X"  });}

Then it can be used as simple as: "test1".traverse();

Scepter answered 25/8, 2014 at 18:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.