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?

0

3 Answers 3

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";
    }
…
Sign up to request clarification or add additional context in comments.

4 Comments

And if you could explain your answer now?
@FelixKling var why? what do you mean?
That's exactly what I was thinking when you just posted the code.
does it make sense to you now?
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.

9 Comments

so I should use .contains?
there is no contains.
@dreamlab: I never said there is.
i know you didn't. but @mikeandike didn't understand.
Btw, downvoter, if anything is wrong with my answer, let me know, I'm happy to correct it.
|
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();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.