How to remove whitespace of a substring

99 Views Asked by At

I am working on a functional programming exercise and I was asked to replace all whitespaces in the string with an hyphen. If I have a string like This is a title, the output should be this-is-a-title.

Now, all cases as described before work but I have an edge case string like this: Peter Is Coming. I would like to strip out the whitespace that is before the Coming so that my final output is peter-is-coming which would be the equivalent output for when I have an initial string of Peter is Coming with no redundant whitespace. I was able to do that of before Peter with ease using the trim method. How do I go about this edge case's?

Note: One of the constraints is that there shouldn't be the use of the replace method.

Thanks.

My code:

function urlSlug(title) {

  const url = title.trim().toLowerCase();
  console.log(url);

  const splitURL = url.split("");
  // console.log(splitURL);

  const urlArr = [];

  const filtered = splitURL.filter(val => {
    if (/\s/.test(val)) {
      
      urlArr.push("-");
    }
    
    else {
      urlArr.push(val);
    }
  });

  return console.log(urlArr.join(""));

}

urlSlug("A Mind Needs Books Like A Sword Needs A Whetstone"); // a-mind-needs-books-like-a-sword-needs-a-whetstone
urlSlug("Hold The Door"); // hold-the-door 
urlSlug(" Peter is  Coming"); // peter-is--coming 

// The last output is what I get but not what I want to achieve.

Update:

Thanks to everybody that answered. I eventually used the code below in relation to my original code and it passed the edge case:


function urlSlug(title) {

  const url = title.trim().toLowerCase();
  console.log(url);

  const splitURL = url.split(/\s+/);
  // console.log(splitURL);

  const urlArr = [];

  const filtered = splitURL.filter(val => {
    if (/\s/.test(val)) {
      
      urlArr.push("-");
    }
    
    else {
      urlArr.push(val);
    }
  });

  return console.log(urlArr.join("-"));

}

3

There are 3 best solutions below

2
Mamun On

The condition if (/\s/.test(val)) doesn't consider consecutive whitespace characters between words.

You can try the following way:

function urlSlug(title) {
  //remove leading and trailing spaces
  //convert to lowercase
  const trimmedTitle = title.trim().toLowerCase();

  //split words array
  const words = trimmedTitle.split(/\s+/);

  //join the words with hyphens
  const slug = words.join("-");

  return slug;
}

console.log(urlSlug("A Mind Needs Books Like A Sword Needs A Whetstone")); //a-mind-needs-books-like-a-sword-needs-a-whetstone
console.log(urlSlug("Hold The Door")); //hold-the-door 
console.log(urlSlug(" Peter is  Coming")); //peter-is-coming

0
William Kliemann On

To solve this issue, you can use the split method to break the string into words, and then use join to concatenate them with hyphens. This way, redundant spaces are automatically removed.

    function urlSlug(title) {
      const url = title.trim().toLowerCase();
      const splitURL = url.split(/\s+/);
      return splitURL.join("-");
    }

    console.log(urlSlug("A Mind Needs Books Like A Sword Needs A Whetstone")); // a-mind-needs-books-like-a-sword-needs-a-whetstone
console.log(urlSlug("Hold The Door")); // hold-the-door
console.log(urlSlug(" Peter is  Coming")); // peter-is-coming

Here, /\s+/ in the split function means that it will break the string at any amount of white space, thus removing redundant spaces. Then join concatenates the words with hyphens, solving your edge case.

2
ewhalenkamp On

You can create a new variable previousWhiteSpace that keeps track of whether the previous iteration of .filter() resulted in whitespace.

Using your current implementation, this doesn't take much of a change (note previousWhiteSpace):

function urlSlug(title) {
  const url = title.trim().toLowerCase();
  console.log(url);

  const splitURL = url.split("");
  // console.log(splitURL);

  const urlArr = [];

  let previousWhiteSpace = false;

  const filtered = splitURL.filter(val => {
    if (/\s/.test(val)) {
      // after making sure val is whitespace, pass harmlessly if previous val was whitespace
      if (!previousWhiteSpace) {
        urlArr.push("-");
        previousWhiteSpace = true;
      }
    }
    else {
      urlArr.push(val);
      previousWhiteSpace = false;
    }
  });

  return console.log(urlArr.join(""));
}

urlSlug("A Mind Needs Books Like A Sword Needs A Whetstone"); // a-mind-needs-books-like-a-sword-needs-a-whetstone
urlSlug("Hold The Door"); // hold-the-door 
urlSlug(" Peter is  Coming"); // peter-is-coming 

However, this can be vastly simplified by splitting url with a whitespace character (\s) instead of "", saving you an extra iteration with filter.

Example:

function urlSlug(title) {
  const url = title.trim().toLowerCase();

  // whitespace regex to match every whitespace character
  const urlArr = url.split(/\s+/);

  return console.log(urlArr.join("-"));
}

urlSlug("A Mind Needs Books Like A Sword Needs A Whetstone"); // a-mind-needs-books-like-a-sword-needs-a-whetstone
urlSlug("Hold The Door"); // hold-the-door 
urlSlug(" Peter is  Coming"); // peter-is-coming 

EDIT: Because it's Javascript, why not take it even further?

Single line solution:

const urlSlug = (title) => console.log(title.trim().toLowerCase().split(/\s+/).join("-"));

urlSlug("A Mind Needs Books Like A Sword Needs A Whetstone"); // a-mind-needs-books-like-a-sword-needs-a-whetstone
urlSlug("Hold The Door"); // hold-the-door 
urlSlug(" Peter is  Coming"); // peter-is-coming