简体   繁体   中英

Need help to reverse a string of words

How can I get following output when I pass following string in function as argument?

  • input: "Reverse this line"

  • output: "esreveR siht enil"

this is my code

function reverseWords(string) {
    var wordArray = string.split(" ");
    var resultWordArray = [];
    var requiredSentance;
    wordArray.forEach(word => {
        if (word == " ") {
            var space = " ";
            resultWordArray.push(space);
        } else {
            var SplittedWord = word.split("");
            var reversedWordsLettersArray = [];
            SplittedWord.forEach(letter => {
                reversedWordsLettersArray.unshift(letter);
                var reversedWord = reversedWordsLettersArray.join("");
                resultWordArray.push(reversedWord);
            })
        }
    })
    var resultSentance = resultWordArray.join(" ");
    console.log(resultSentance);
}
reverseWords("Reverse this line");

which is returning this as output:

"R eR veR eveR reveR sreveR esreveR t ht iht siht l il nil enil"

What am I missing here?

You can split the string into words and map through each word, splitting it into a character array and reverse the array, then join back the words into a single string. Like this:

string.split(' ').map(s => s.split('').reverse().join('')).join(' ')

To explain the code:

string.split(' ')

This line splits the whole string into array of words, "Reverse this line" becomes ["Reverse", "this", "line"] (note that the spaces are gone). Keep in mind that double spaces will be still split as a single space.

Since we now have an array, you can iterate the whole string using the .map function. It works similarly to how you've tried to use the .forEach , with the difference that the .map function will return a new array with modified values which are returned in each iteration of the .map callback function. Make sure to return something, or the values will be undefined ! The arrow function from ES2015+ has implicit return as you see in the example above, but if you were to use => {...} , the block needs an explicit return statement to work.

The code of the .map function callback

s => s.split('').reverse().join('')

Receives a s , which is a single word from the array above, splits the word by empty string, which is a workaround to split a string into characters. For example, "Reverse" becomes ["R", "e", "v", "e", "r", "s", "e"] . The .reverse() function's name is quite descriptive, it just reverses the array. But be careful! It mutates the array, so if you call the .reverse() function on a random array, it will be reversed from that line on. This could cause some issues if you're not careful. Lastly, the .join('') puts the reversed array of characters back into a single string word.

And finally the .join(' ') at the end puts the mapped array, which now contains reversed words, back together with spaces in-between, similarly to how .join('') puts the array of characters back into a single word.

Using your code specifically, you are very close with what you are trying to do. You just need to move the declaration of the reversedWord variable out of the forEach loop, update inside the forEach loop, which will eventually be defined with the entire reversed word.

function reverseWords(string) {

var wordArray = string.split(" ");
var resultWordArray = [];
var requiredSentance;

wordArray.forEach(word => {

  if (word == " ") {
    var space = " ";
    resultWordArray.push(space);

  } else {
    var SplittedWord = word.split("");
    var reversedWordsLettersArray = [];
    var reversedWord; //define variable here 

    SplittedWord.forEach(letter => {
      reversedWordsLettersArray.unshift(letter);
      reversedWord = reversedWordsLettersArray.join("");
    })
    resultWordArray.push(reversedWord); // push it here
  }
})

var resultSentance = resultWordArray.join(" ");
  console.log(resultSentance);
}


reverseWords("Reverse this line");

Here's an interesting approach that doesn't require a call to .map() , if you think outside the box a bit about the string processing:

 function reverseWords(string, delimiter = ' ') { return string .split('').reverse().join('') .split(delimiter).reverse().join(delimiter); } console.log(reverseWords('Reverse this line')); 

If you reverse character-by-character on the first pass, you can then split the string by the word delimiter (in this case ' ' ) and reverse the words to put them back in the original order on the second pass.

After benchmarking this approach, I've found that it is twice as fast as the currently accepted answer .

Another nice feature about this function is that you can specify the word delimiter as the optional second argument:

 function reverseWords(string, delimiter = ' ') { return string .split('').reverse().join('') .split(delimiter).reverse().join(delimiter); } console.log(reverseWords('Reverse this line', '\\t')); 

Here's a recursive method that just iterates once over the string:

function reverseWords(string){
  return (function f(str, i, reversed){
    if (!str[i])
      return reversed;

    if (str[i] == ' ')
      return reversed + ' ' + f(str, i + 1, '');

    return f(str, i + 1, str[i] + reversed);
  })(string, 0, '');
}

console.log(reverseWords("Reverse this line"));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM