johntc121 johntc121 - 26 days ago 13
Javascript Question

How to remove spaces and special characters from string?

I have a function that returns true if a character is a form of punctuation and I'm trying to write another function that accepts a string and removes the spaces and punctuation marks while calling the first function. I got most of it I think. But now I'm stuck. Any help is appreciated.

var isPunct = function(ch) {

if (ch = ch.match(/[,.!?;:'-]/g))
return true
else
return false
}

//B

var compress = function(s) {
var result = "";

//loop to traverse s
for (var i = 0; i < s.length; i++) {
if (!(isPunct(ch));
//(isPunct(s.charAt(i) || s.charAt(i) == " "));
//do nothing
else
result = result + !compress(i)
}

return result
}

Answer

Some issues:

  • The inner condition should in fact be the opposite: you want to do nothing when it is a punctuation character, i.e. you don't want to add it to the result. Only in the other case you want to do that.

  • The call !compress(i) is wrong: first of all that function expects a string, not an index, and it returns a string, not a boolean (so to perform ! on it). It seems like you want to call your function recursively, and although that is an option, you are also iterating over the string. You should do one of the two: recursion or iteration.

  • You reference a variable ch in the compress function which you have not defined there.

So, if you want to write compress the iteration way, change your code as follows:

var compress = function(s) {
    var result = "", ch; // define ch.

    //loop to traverse s
    for (var i = 0; i < s.length; i++) {
        ch = s[i]; // initialise ch.
        if (!isPunct(ch)) result = result + ch; // only add when not punctuation
    }
    return result;
}

If on the other hand you want to keep your recursive call to compress, then you should do away with your for loop:

var compress = function(s) {
    var result = "", ch, rest;

    if (s.length == 0) return '';
    result = compress(s.substr(1)); // recursive call
    ch = s[0];
    if (!isPunct(ch)) result = ch + result;
    return result;
}

The function isPunct also has a strange thing happening: it assigns a boolean value to ch in the if expression. This does not make your function malfunction, but that assignment serves no purpose: the match method already returns the boolean you need for your if condition.

It is also not really nice-looking to first evaluate a boolean expression in an if to then return that same value in the form of false and true. This you can do by just returning the evaluated expression itself:

var isPunct = function(ch) {
    return ch.match(/[,.!?;:'-]/g);
}

On a final note, you don't really need the isPunct function if you only use it in compress. The whole logic can be performed in one function only, like this:

let compress = s => s.replace(/[,.!?;:'-]/g,'');
// Demo:  
console.log(compress('a,b,c')); // abc

If you prefer to keep isPunct and don't want to repeat the regular expression elsewhere, then you can do the replace like this:

let isPunct = ch => ch.match(/[,.!?;:'-]/g);

let compress = s => Array.from(s).filter(ch => !isPunct(ch)).join('');
// Demo:  
console.log(compress('a,b,c')); // abc

Note how the use of ES6 arrow functions and ES5 Array methods makes the code quite lean.