0

I want to reverse the words in a sentence (string) but keep the punctuation at the same place.

example: greetings! how are you today?

to result: today! you are how greetings?

So far I've done this but I can't really remember how should I approach the part with the punctuation. I thought of splitting like ('') this and looping and checking with regex but that looks like a daunting task. It would help a lot if you use my codeblock to upgrade rather than writing super complex functions of your own, after all I am new and I might not be able to read them lol.

let str = 'greetings! how are you today?'
let stringArr = ''

function strReverser(str) {
  stringArr = str.split(' ').reverse().join(' ')

  return stringArr
}
stringArr = strReverser(str)
console.log(stringArr)

strReverser(str)
mplungjan
  • 169,008
  • 28
  • 173
  • 236
s74n
  • 19
  • 3
  • @ghosh, that's about reversing words but keep the order. OP wants to keep the `.,?!` symbols in place but reverse the order of the words. – Emiel Zuurbier Nov 02 '20 at 12:41

6 Answers6

3

let str = "greetings! how are you today?";

function strReverser(str) {
  const regex = /\w+/g;
  const words = str.match(regex);
  return str.replace(regex, () => words.pop());
}

console.log(strReverser(str));
  • Edited to track words instead of punctuation. – Michael S. Molina Nov 02 '20 at 13:40
  • Nice and shorter than any of the other answers – mplungjan Nov 02 '20 at 13:42
  • I am really thankful for your solution it looks clean. One thing I can't yet grasp is how pop works in this scenario. Because from what I understand when there is match to the regex you pop that character out of the array. How does it come back on it's place then? – s74n Nov 02 '20 at 15:10
  • @s74n We don't need to push back the word because we work on top of the string. First we create an array containing all the words. When we do a str.replace we are looping through all the words again but this time we are replacing them backwards using pop. So the words array is just a helper variable, not the string content. – Michael S. Molina Nov 02 '20 at 15:21
  • @s74n Can you please mark the question as answered? – Michael S. Molina Nov 03 '20 at 12:54
0

Save the punctuation and reinsert it

let str = 'greetings! how? are you, today?'

function strReverser(str) {
  let stringArr = str.split(' ')
  const punct = []
  stringArr = stringArr.map(str => { 
    punct.push(str.replace(/[^\W]/g,"")); // save the punctuation
    return str.replace(/\W/g,"") })       // remove the punctuation
  stringArr = stringArr
    .reverse()
    .map((str,i) => str + punct[i]); // insert where needed
  return stringArr.join(" ");
}
let revString = strReverser(str);
console.log(revString)
mplungjan
  • 169,008
  • 28
  • 173
  • 236
0

This does get a little more involved:

let str = 'greetings! how are you today?'
let stringArr = ''
const puncRE = /([?!.,:;])$/

function strReverser(str){
    const words = str.split(' ')
    const words_p = words.map(word => {
      const match = word.match(puncRE)
        if (match) {
          return match[0]
        }
        return undefined
    })
    return words
      .reverse()
      .map(word => word.replace(puncRE, ''))
      .map((w, i) => {
        if(words_p[i]) {
          return `${w}${words_p[i]}`
        }
        return w
      }).join(' ') 
}
stringArr = strReverser(str)
console.log(stringArr)
thedude
  • 9,388
  • 1
  • 29
  • 30
0

When I finished the code there were already two answers. But at least mine does in less iterations:

let str = 'greetings! how are you today?'
let stringArr = ''

function strReverser(str) {
    const punctuationRegex = /([?!.,:;])$/;
    let words = [];
    let word = '';
    let wordCount = 0;
    let punctuations = {};
    for (let i = 0; i < str.length; i += 1) {
        const char = str[i];
        if (char == ' ') {
            wordCount += 1;
            words.unshift(word);
            word = '';
            continue;
        }
        if (punctuationRegex.test(char)) {
            punctuations[wordCount] = char;
            continue;
        }
        word += char;
    }
    words.unshift(word);

    let result = '';
    for (let i = 0; i < words.length; i += 1) {
        result += words[i];
        if (punctuations[i] != null) {
            result += punctuations[i];
        }
        result += ' ';
    }
    return result
}
stringArr = strReverser(str)
console.log(stringArr)
Leonardo da Silva
  • 1,285
  • 2
  • 10
  • 25
0

You can extract the puntuation and the replace it in the reverse order:

let str = 'greetings! how are you today?'
let stringArr = ''

function strReverser(str) {
  const puntuation = str.match(/\W/g).filter((s) => s !== " ").reverse();
  
  return str.split(' ').reverse().map((st) => {
    const p = st.match(/\W/g);
    return p ? st.replace(p, puntuation.pop()) : st;
  }, '').join(' ');
}

stringArr = strReverser(str)
console.log(stringArr)
Greedo
  • 3,438
  • 1
  • 13
  • 28
0

let str = 'greetings! how are you today?'
let stringArr = ''

function strReverser(str) {
  let words = str.split(' ');

  // Regex to find anything that's not alphanumeric
  let regex = /[^0-9a-zA-Z]/gm;

  // Find any puncutation and collect it.
  let allPun = [];
  for (let i = 0; i < words.length; i++) {
    if (words[i].match(regex)) {
      let punctuation = words[i].match(regex)[0];
      words[i] = words[i].replace(punctuation, '');
      allPun.push(punctuation);
    } else {
      allPun.push('');
    }
  }

  // Reverse all the words
  words = words.reverse();

  // Add in the punctuation
  for (let i = 0; i < words.length; i++) {
    words[i] = words[i] + allPun[i];
  }

  // Join the words back together.
  stringArr = words.join(' ')

  return stringArr
}

stringArr = strReverser(str)
console.log(stringArr)
mplungjan
  • 169,008
  • 28
  • 173
  • 236