Home > database >  JavaScript array mutating split(" ") vs spread operator
JavaScript array mutating split(" ") vs spread operator

Time:01-21

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()

CodePudding user response:

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 ...

CodePudding user response:

I optimized your original function a bit, while trying to understand your problem. Since @derpirscher already answered your question, I just want to add this as an inspiration (and not just throw it away :-)

With palindromes you compare letters, so there's no need to split the sentence into words.

const palindromes = (str) => {
    const regex = /[^a-zA-Z]/g; // No need to specify all the characters, also removes whitespaces
    const cStr = str.toLowerCase().replace(regex, ""); // No need to convert to array and back
    const revStr = cStr.split("").reverse().join("");
    return cStr === revStr; // This already returns true or false
};
  • Related