Search code examples
javascriptarraysslicereverse

JavaScript array mutating split(" ") vs spread operator


I'm trying to check whether some sentence is a palindrome. Word breaks and punctuation don't count.

This code using cStr.split(" ") DOES NOT accomplish the task. Splitting on whitespace (" "), it seems like reverse() does nothing.

const palindromes = (str) => {
    const regex = /[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/g;
    const cStr = str.toLowerCase().replace(regex, "").split(" ").join("");
    const revStr = cStr.split(" ").slice().reverse().join("");
    return cStr === revStr ? true : false;
};

UPDATED THOUGHTS: After I join the original string cStr at the end, the characters are all collapsed. In the incorrect code I split on "whitespace" (split(" ")) which does not exist, so the code stops executing but doesn't throw an error?

The same code using [...cStr] or cStr.split("") DOES accomplish the task:

const revStr = cStr.split("").slice().reverse().join("");

// or
const revStr = [...cStr].slice().reverse().join("");

How is the "separator"; /""/ or /" "/ having this effect?

If separator is an empty string (""), str is converted to an array of each of its UTF-16 "characters", without empty strings on either ends of the resulting string.

Relevant question to array mutating: reverse-array-in-javascript-without-mutating-original-array

Relevant question to string manipulation: character-array-from-string

Split() doc: String.prototype.split()


Solution

  • Seems you have read the docs of string.split but not fully understood them. If you pass a separator, that doesn't exist in the string, it just returns an array with one element, this element being the whole string. Whereas if you split by an empty separator, it will split after every character.

    let astring = "nowhitespacehere";
    let splitstring1 = astring.split(" ");
    console.log(splitstring1);
    let splitstring2 = astring.split("");
    console.log(splitstring2);

    Well, in your first approach you remove all whitespaces from your string by

    str.split(" ").join("");
    

    Then later on you do

    cStr.split(" ").slice().reverse().join("");
    

    If you separate those steps do

    1. .split(" ") by whitespace. There is no whitespace anymore, thus, this returns an array with one element [cStr]

    2. you .slice() from that array, which gives you another 1-element array [cStr]

    3. you .reverse() that 1-element array, which gives you -- surprise surprise -- another 1-element arrray [cStr]

    4. you .join("") the elements in this 1-element array with an empty separator, which gives you cStr

    In your second approach you do

    cStr.split("").slice().reverse().join("");
    

    The crucial difference is the first split("") by an empty separator, which splits the string after every character

    No, your first approach doesn't "stop executing" it just does what you told it to do, split by a non-existant separator. And why would or should that throw an error? It just does, what the split is supposed to do. Add up all characters until you find a separator. If none is to be found, of course it will add up the whole string to the first token ...