Taking a string and reversing certain words — Javascript












1















Write a function that takes in a string of one or more words, and returns the same string, but with all five or more letter words reversed. Strings passed in will consist of only letters and spaces. Spaces will be included only when more than one word is present.



The code I wrote reverses the whole string. I believe it is something with the if statement, it is not catching words greater than 5. My thinking when writing the code is to first convert the string into an array of words, use a for loop to run through the arrays and find the words that are greater than 5, then reverse the words greater than 5. I have found similar problems and this is how far I got searching for help. I'm stuck, any help would be greatly appreciated! I am new to coding and learning Javascript.



function spinWords(backward){

var sentence = "";
var separate = backward.split("");

for (var i = separate.length - 1; i >= 0; i--){
if (separate[i].length >= 1){
sentence += separate[i].split("").reverse().join("");
}
else {
sentence += "" + separate[i];
}
}
return sentence;
}

spinWords("Hey fellow warriors");









share|improve this question























  • Your problem statement isnt 100% clear. Are you saying you only want to reverse words that are 5 characters or more long?

    – Paul Rooney
    Dec 30 '18 at 23:06
















1















Write a function that takes in a string of one or more words, and returns the same string, but with all five or more letter words reversed. Strings passed in will consist of only letters and spaces. Spaces will be included only when more than one word is present.



The code I wrote reverses the whole string. I believe it is something with the if statement, it is not catching words greater than 5. My thinking when writing the code is to first convert the string into an array of words, use a for loop to run through the arrays and find the words that are greater than 5, then reverse the words greater than 5. I have found similar problems and this is how far I got searching for help. I'm stuck, any help would be greatly appreciated! I am new to coding and learning Javascript.



function spinWords(backward){

var sentence = "";
var separate = backward.split("");

for (var i = separate.length - 1; i >= 0; i--){
if (separate[i].length >= 1){
sentence += separate[i].split("").reverse().join("");
}
else {
sentence += "" + separate[i];
}
}
return sentence;
}

spinWords("Hey fellow warriors");









share|improve this question























  • Your problem statement isnt 100% clear. Are you saying you only want to reverse words that are 5 characters or more long?

    – Paul Rooney
    Dec 30 '18 at 23:06














1












1








1








Write a function that takes in a string of one or more words, and returns the same string, but with all five or more letter words reversed. Strings passed in will consist of only letters and spaces. Spaces will be included only when more than one word is present.



The code I wrote reverses the whole string. I believe it is something with the if statement, it is not catching words greater than 5. My thinking when writing the code is to first convert the string into an array of words, use a for loop to run through the arrays and find the words that are greater than 5, then reverse the words greater than 5. I have found similar problems and this is how far I got searching for help. I'm stuck, any help would be greatly appreciated! I am new to coding and learning Javascript.



function spinWords(backward){

var sentence = "";
var separate = backward.split("");

for (var i = separate.length - 1; i >= 0; i--){
if (separate[i].length >= 1){
sentence += separate[i].split("").reverse().join("");
}
else {
sentence += "" + separate[i];
}
}
return sentence;
}

spinWords("Hey fellow warriors");









share|improve this question














Write a function that takes in a string of one or more words, and returns the same string, but with all five or more letter words reversed. Strings passed in will consist of only letters and spaces. Spaces will be included only when more than one word is present.



The code I wrote reverses the whole string. I believe it is something with the if statement, it is not catching words greater than 5. My thinking when writing the code is to first convert the string into an array of words, use a for loop to run through the arrays and find the words that are greater than 5, then reverse the words greater than 5. I have found similar problems and this is how far I got searching for help. I'm stuck, any help would be greatly appreciated! I am new to coding and learning Javascript.



function spinWords(backward){

var sentence = "";
var separate = backward.split("");

for (var i = separate.length - 1; i >= 0; i--){
if (separate[i].length >= 1){
sentence += separate[i].split("").reverse().join("");
}
else {
sentence += "" + separate[i];
}
}
return sentence;
}

spinWords("Hey fellow warriors");






javascript arrays string






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Dec 30 '18 at 23:01









xendezxendez

61




61













  • Your problem statement isnt 100% clear. Are you saying you only want to reverse words that are 5 characters or more long?

    – Paul Rooney
    Dec 30 '18 at 23:06



















  • Your problem statement isnt 100% clear. Are you saying you only want to reverse words that are 5 characters or more long?

    – Paul Rooney
    Dec 30 '18 at 23:06

















Your problem statement isnt 100% clear. Are you saying you only want to reverse words that are 5 characters or more long?

– Paul Rooney
Dec 30 '18 at 23:06





Your problem statement isnt 100% clear. Are you saying you only want to reverse words that are 5 characters or more long?

– Paul Rooney
Dec 30 '18 at 23:06












2 Answers
2






active

oldest

votes


















3














You might find the logic a lot easier if you used a regular expression to match 5 or more word characters in a row, and use a replacer function to reverse them:






function spinWords(backward) {
return backward.replace(/w{5,}/g, word => word.split('').reverse().join(''));
}

console.log(spinWords("Hey fellow warriors"));





To fix your code, you should split the input string (the variabla named backward) by a space, not by the empty string, to get an array of words, then iterate through that array (starting from the beginning, not at the end), checking for each word's length and concatenating with sentence:






function spinWords(backward) {

var sentence = "";
var separate = backward.split(" ");

for (var i = 0; i < separate.length; i++) {
if (sentence) sentence += ' ';
if (separate[i].length >= 5) {
sentence += separate[i].split("").reverse().join("");
} else {
sentence += separate[i];
}
}
return sentence;
}

console.log(spinWords("Hey fellow warriors"));








share|improve this answer































    0














    Below is a discussion about a possible way to approach this problem. It is not what I would likely do for a question as simple as this, but it demonstrates a mindset that makes it easier to solve many problems, and to reuse your work as you do so.





    Breaking the problem down



    You want to do several things here, so it might help to break the problem down into steps.



    At the core, you want to reverse certain words. So why not write a function to do only that? It should be simple. Here is one version:



    const reverseWord = word => word.split('').reverse().join('')
    reverseWord('word') //=> 'drow'


    But you only want to do this to words whose length is at least five. Rather than rewriting our existing function, we can use it to write the more complex one:



    const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word
    reverseIfGte5('word') //=> 'word'
    reverseIfGte5('supercalifragilisticexpialidocious')
    //=> 'suoicodilaipxecitsiligarfilacrepus')


    Note that here, we write reverseIfGte5 using reverseWord. So our reverseWord function is also available to be reused if we choose, but also so that each function is doing something simple.



    We could now write spinWord in terms of this function, via



    const spinWords = sentence => sentence.split(/s+/).map(reverseIfGte5).join(' ')

    spinWords('Hey fellow warriors') //=> 'Hey wollef sroirraw'


    This does what's expected. And it might be a good place to stop. However...



    Do only one thing per function



    Our spinWords function above is responsible for two things:




    • finding the words in the sentence

    • applying our reversing function to each


    Ideally, a function should be responsible for one thing an one thing only. (There is some judgment to be made in deciding how such responsibilities break down, of course.)



    It might be useful to break this apart. We can do that in different ways. Here's a simple one:



    const updateWords = wordFn => sentence => sentence.split(/s+/).map(wordFn).join(' ')
    const spinWords = updateWords(reverseIfGte5)


    Now we have a reusable function, which we could use, for instance, with an obvious capitalizeFirstLetter function like this:



    const titleCase = updateWords(capitalizeFirstLetter)
    titleCase('Hey fellow warriors') //=> 'Hey Fellow Warriors')


    Fixing bugs



    Our code now looks like this:



    const updateWords = wordFn => sentence => sentence.split(/s+/).map(wordFn).join(' ')
    const reverseWord = word => word.split('').reverse().join('')
    const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word
    const spinWords = updateWords(reverseIfGte5)


    These functions are ordered from the most likely to the least likely to be reusable.



    Note that the total code here, when using such reusable functions, is a bit longer than this plain version:



    const spinWords = sentence => sentence.split(/s+/).map(
    word => word.length >= 5 ? word.split('').reverse().join('') : word
    ).join(' ')


    But our version has several advantages. Obviously, reusability is one. But another is that with the problem broken down into small pieces, if we find a problem, we know where look to for a solution.



    And guess what, there is in fact a potential bug in this solution.



    If we call this function with 'Hey fellow warriors', we return 'Hey wollef oirraw' instead of the expected 'Hey wollef sroirraw'. Our spacing is off.



    Because this problem is broken down into distinct functions, there is no question about which function we need to change in order to fix this. Clearly it is the function responsible for pulling apart and putting back together the sentence, updateWords. There is one simple fix to this, changing from



    const updateWords = wordFn => sentence => sentence.split(/s+/).map(wordFn).join(' ')


    to



    const updateWords = wordFn => sentence => sentence.split(' ').map(wordFn).join(' ')


    but we might be better off using a variant of the answer from CertainPerformance, and rewriting it like this:



    const updateWords = wordFn => sentence => sentence.replace(/w+/g, wordFn)


    This fixes the bug and actually handles more cases than we could have originally. (Note that it now deals with punctuation characters as well):



    spinWords('Hey, fellow warriors!') //=> 'Hey, wollef sroirraw!'


    The important point is that in order to fix our bug, we were able to isolate the function responsible and change it without changing anything else.



    Working code



    This is what we have arrived at:






    const updateWords = wordFn => sentence => sentence.replace(/w+/g, wordFn)
    const reverseWord = word => word.split('').reverse().join('')
    const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word

    const spinWords = updateWords(reverseIfGte5)

    console.log(spinWords('Hey, fellow warriors!'))





    We have broken the problem down into two fairly reusable functions (reverseWord and updateWords), and two very specific to our problem (reverseIfGte5 and spinWords.) Each has a well-defined responsibility, and they are easy to test in isolation.



    Extending further



    This is as far as I would likely go with such a function. But because my personal library often includes a function, when, which is already a generalization of one of these, sometimes I might prefer to build on that:



    const when = (cond, then) => val => cond(val) ? then(val) : val
    const reverseIfGte5 = when(word => word.length >= 5, reverseWord)


    I created when because there are times when I want to use an altered version of my input if some condition is true about it and use it unaltered if the condition is false. That is exactly what reverseIfGte5 needs to do, so it's useful to build it on top of when.



    This is how utility libraries are built. Several specific problems have obvious connections and more general solutions to them are written to handle them. If these such solutions are generic enough, they are candidates for inclusion in your personal library or your team's library. And if they are useful to a wider audience, they might get included in a general-purpose utility library.



    I'm one of the authors of Ramda, a utility library for functional programming in JS, and this is exactly how it has been built.






    share|improve this answer

























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53982133%2ftaking-a-string-and-reversing-certain-words-javascript%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      3














      You might find the logic a lot easier if you used a regular expression to match 5 or more word characters in a row, and use a replacer function to reverse them:






      function spinWords(backward) {
      return backward.replace(/w{5,}/g, word => word.split('').reverse().join(''));
      }

      console.log(spinWords("Hey fellow warriors"));





      To fix your code, you should split the input string (the variabla named backward) by a space, not by the empty string, to get an array of words, then iterate through that array (starting from the beginning, not at the end), checking for each word's length and concatenating with sentence:






      function spinWords(backward) {

      var sentence = "";
      var separate = backward.split(" ");

      for (var i = 0; i < separate.length; i++) {
      if (sentence) sentence += ' ';
      if (separate[i].length >= 5) {
      sentence += separate[i].split("").reverse().join("");
      } else {
      sentence += separate[i];
      }
      }
      return sentence;
      }

      console.log(spinWords("Hey fellow warriors"));








      share|improve this answer




























        3














        You might find the logic a lot easier if you used a regular expression to match 5 or more word characters in a row, and use a replacer function to reverse them:






        function spinWords(backward) {
        return backward.replace(/w{5,}/g, word => word.split('').reverse().join(''));
        }

        console.log(spinWords("Hey fellow warriors"));





        To fix your code, you should split the input string (the variabla named backward) by a space, not by the empty string, to get an array of words, then iterate through that array (starting from the beginning, not at the end), checking for each word's length and concatenating with sentence:






        function spinWords(backward) {

        var sentence = "";
        var separate = backward.split(" ");

        for (var i = 0; i < separate.length; i++) {
        if (sentence) sentence += ' ';
        if (separate[i].length >= 5) {
        sentence += separate[i].split("").reverse().join("");
        } else {
        sentence += separate[i];
        }
        }
        return sentence;
        }

        console.log(spinWords("Hey fellow warriors"));








        share|improve this answer


























          3












          3








          3







          You might find the logic a lot easier if you used a regular expression to match 5 or more word characters in a row, and use a replacer function to reverse them:






          function spinWords(backward) {
          return backward.replace(/w{5,}/g, word => word.split('').reverse().join(''));
          }

          console.log(spinWords("Hey fellow warriors"));





          To fix your code, you should split the input string (the variabla named backward) by a space, not by the empty string, to get an array of words, then iterate through that array (starting from the beginning, not at the end), checking for each word's length and concatenating with sentence:






          function spinWords(backward) {

          var sentence = "";
          var separate = backward.split(" ");

          for (var i = 0; i < separate.length; i++) {
          if (sentence) sentence += ' ';
          if (separate[i].length >= 5) {
          sentence += separate[i].split("").reverse().join("");
          } else {
          sentence += separate[i];
          }
          }
          return sentence;
          }

          console.log(spinWords("Hey fellow warriors"));








          share|improve this answer













          You might find the logic a lot easier if you used a regular expression to match 5 or more word characters in a row, and use a replacer function to reverse them:






          function spinWords(backward) {
          return backward.replace(/w{5,}/g, word => word.split('').reverse().join(''));
          }

          console.log(spinWords("Hey fellow warriors"));





          To fix your code, you should split the input string (the variabla named backward) by a space, not by the empty string, to get an array of words, then iterate through that array (starting from the beginning, not at the end), checking for each word's length and concatenating with sentence:






          function spinWords(backward) {

          var sentence = "";
          var separate = backward.split(" ");

          for (var i = 0; i < separate.length; i++) {
          if (sentence) sentence += ' ';
          if (separate[i].length >= 5) {
          sentence += separate[i].split("").reverse().join("");
          } else {
          sentence += separate[i];
          }
          }
          return sentence;
          }

          console.log(spinWords("Hey fellow warriors"));








          function spinWords(backward) {
          return backward.replace(/w{5,}/g, word => word.split('').reverse().join(''));
          }

          console.log(spinWords("Hey fellow warriors"));





          function spinWords(backward) {
          return backward.replace(/w{5,}/g, word => word.split('').reverse().join(''));
          }

          console.log(spinWords("Hey fellow warriors"));





          function spinWords(backward) {

          var sentence = "";
          var separate = backward.split(" ");

          for (var i = 0; i < separate.length; i++) {
          if (sentence) sentence += ' ';
          if (separate[i].length >= 5) {
          sentence += separate[i].split("").reverse().join("");
          } else {
          sentence += separate[i];
          }
          }
          return sentence;
          }

          console.log(spinWords("Hey fellow warriors"));





          function spinWords(backward) {

          var sentence = "";
          var separate = backward.split(" ");

          for (var i = 0; i < separate.length; i++) {
          if (sentence) sentence += ' ';
          if (separate[i].length >= 5) {
          sentence += separate[i].split("").reverse().join("");
          } else {
          sentence += separate[i];
          }
          }
          return sentence;
          }

          console.log(spinWords("Hey fellow warriors"));






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Dec 30 '18 at 23:03









          CertainPerformanceCertainPerformance

          93.3k165384




          93.3k165384

























              0














              Below is a discussion about a possible way to approach this problem. It is not what I would likely do for a question as simple as this, but it demonstrates a mindset that makes it easier to solve many problems, and to reuse your work as you do so.





              Breaking the problem down



              You want to do several things here, so it might help to break the problem down into steps.



              At the core, you want to reverse certain words. So why not write a function to do only that? It should be simple. Here is one version:



              const reverseWord = word => word.split('').reverse().join('')
              reverseWord('word') //=> 'drow'


              But you only want to do this to words whose length is at least five. Rather than rewriting our existing function, we can use it to write the more complex one:



              const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word
              reverseIfGte5('word') //=> 'word'
              reverseIfGte5('supercalifragilisticexpialidocious')
              //=> 'suoicodilaipxecitsiligarfilacrepus')


              Note that here, we write reverseIfGte5 using reverseWord. So our reverseWord function is also available to be reused if we choose, but also so that each function is doing something simple.



              We could now write spinWord in terms of this function, via



              const spinWords = sentence => sentence.split(/s+/).map(reverseIfGte5).join(' ')

              spinWords('Hey fellow warriors') //=> 'Hey wollef sroirraw'


              This does what's expected. And it might be a good place to stop. However...



              Do only one thing per function



              Our spinWords function above is responsible for two things:




              • finding the words in the sentence

              • applying our reversing function to each


              Ideally, a function should be responsible for one thing an one thing only. (There is some judgment to be made in deciding how such responsibilities break down, of course.)



              It might be useful to break this apart. We can do that in different ways. Here's a simple one:



              const updateWords = wordFn => sentence => sentence.split(/s+/).map(wordFn).join(' ')
              const spinWords = updateWords(reverseIfGte5)


              Now we have a reusable function, which we could use, for instance, with an obvious capitalizeFirstLetter function like this:



              const titleCase = updateWords(capitalizeFirstLetter)
              titleCase('Hey fellow warriors') //=> 'Hey Fellow Warriors')


              Fixing bugs



              Our code now looks like this:



              const updateWords = wordFn => sentence => sentence.split(/s+/).map(wordFn).join(' ')
              const reverseWord = word => word.split('').reverse().join('')
              const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word
              const spinWords = updateWords(reverseIfGte5)


              These functions are ordered from the most likely to the least likely to be reusable.



              Note that the total code here, when using such reusable functions, is a bit longer than this plain version:



              const spinWords = sentence => sentence.split(/s+/).map(
              word => word.length >= 5 ? word.split('').reverse().join('') : word
              ).join(' ')


              But our version has several advantages. Obviously, reusability is one. But another is that with the problem broken down into small pieces, if we find a problem, we know where look to for a solution.



              And guess what, there is in fact a potential bug in this solution.



              If we call this function with 'Hey fellow warriors', we return 'Hey wollef oirraw' instead of the expected 'Hey wollef sroirraw'. Our spacing is off.



              Because this problem is broken down into distinct functions, there is no question about which function we need to change in order to fix this. Clearly it is the function responsible for pulling apart and putting back together the sentence, updateWords. There is one simple fix to this, changing from



              const updateWords = wordFn => sentence => sentence.split(/s+/).map(wordFn).join(' ')


              to



              const updateWords = wordFn => sentence => sentence.split(' ').map(wordFn).join(' ')


              but we might be better off using a variant of the answer from CertainPerformance, and rewriting it like this:



              const updateWords = wordFn => sentence => sentence.replace(/w+/g, wordFn)


              This fixes the bug and actually handles more cases than we could have originally. (Note that it now deals with punctuation characters as well):



              spinWords('Hey, fellow warriors!') //=> 'Hey, wollef sroirraw!'


              The important point is that in order to fix our bug, we were able to isolate the function responsible and change it without changing anything else.



              Working code



              This is what we have arrived at:






              const updateWords = wordFn => sentence => sentence.replace(/w+/g, wordFn)
              const reverseWord = word => word.split('').reverse().join('')
              const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word

              const spinWords = updateWords(reverseIfGte5)

              console.log(spinWords('Hey, fellow warriors!'))





              We have broken the problem down into two fairly reusable functions (reverseWord and updateWords), and two very specific to our problem (reverseIfGte5 and spinWords.) Each has a well-defined responsibility, and they are easy to test in isolation.



              Extending further



              This is as far as I would likely go with such a function. But because my personal library often includes a function, when, which is already a generalization of one of these, sometimes I might prefer to build on that:



              const when = (cond, then) => val => cond(val) ? then(val) : val
              const reverseIfGte5 = when(word => word.length >= 5, reverseWord)


              I created when because there are times when I want to use an altered version of my input if some condition is true about it and use it unaltered if the condition is false. That is exactly what reverseIfGte5 needs to do, so it's useful to build it on top of when.



              This is how utility libraries are built. Several specific problems have obvious connections and more general solutions to them are written to handle them. If these such solutions are generic enough, they are candidates for inclusion in your personal library or your team's library. And if they are useful to a wider audience, they might get included in a general-purpose utility library.



              I'm one of the authors of Ramda, a utility library for functional programming in JS, and this is exactly how it has been built.






              share|improve this answer






























                0














                Below is a discussion about a possible way to approach this problem. It is not what I would likely do for a question as simple as this, but it demonstrates a mindset that makes it easier to solve many problems, and to reuse your work as you do so.





                Breaking the problem down



                You want to do several things here, so it might help to break the problem down into steps.



                At the core, you want to reverse certain words. So why not write a function to do only that? It should be simple. Here is one version:



                const reverseWord = word => word.split('').reverse().join('')
                reverseWord('word') //=> 'drow'


                But you only want to do this to words whose length is at least five. Rather than rewriting our existing function, we can use it to write the more complex one:



                const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word
                reverseIfGte5('word') //=> 'word'
                reverseIfGte5('supercalifragilisticexpialidocious')
                //=> 'suoicodilaipxecitsiligarfilacrepus')


                Note that here, we write reverseIfGte5 using reverseWord. So our reverseWord function is also available to be reused if we choose, but also so that each function is doing something simple.



                We could now write spinWord in terms of this function, via



                const spinWords = sentence => sentence.split(/s+/).map(reverseIfGte5).join(' ')

                spinWords('Hey fellow warriors') //=> 'Hey wollef sroirraw'


                This does what's expected. And it might be a good place to stop. However...



                Do only one thing per function



                Our spinWords function above is responsible for two things:




                • finding the words in the sentence

                • applying our reversing function to each


                Ideally, a function should be responsible for one thing an one thing only. (There is some judgment to be made in deciding how such responsibilities break down, of course.)



                It might be useful to break this apart. We can do that in different ways. Here's a simple one:



                const updateWords = wordFn => sentence => sentence.split(/s+/).map(wordFn).join(' ')
                const spinWords = updateWords(reverseIfGte5)


                Now we have a reusable function, which we could use, for instance, with an obvious capitalizeFirstLetter function like this:



                const titleCase = updateWords(capitalizeFirstLetter)
                titleCase('Hey fellow warriors') //=> 'Hey Fellow Warriors')


                Fixing bugs



                Our code now looks like this:



                const updateWords = wordFn => sentence => sentence.split(/s+/).map(wordFn).join(' ')
                const reverseWord = word => word.split('').reverse().join('')
                const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word
                const spinWords = updateWords(reverseIfGte5)


                These functions are ordered from the most likely to the least likely to be reusable.



                Note that the total code here, when using such reusable functions, is a bit longer than this plain version:



                const spinWords = sentence => sentence.split(/s+/).map(
                word => word.length >= 5 ? word.split('').reverse().join('') : word
                ).join(' ')


                But our version has several advantages. Obviously, reusability is one. But another is that with the problem broken down into small pieces, if we find a problem, we know where look to for a solution.



                And guess what, there is in fact a potential bug in this solution.



                If we call this function with 'Hey fellow warriors', we return 'Hey wollef oirraw' instead of the expected 'Hey wollef sroirraw'. Our spacing is off.



                Because this problem is broken down into distinct functions, there is no question about which function we need to change in order to fix this. Clearly it is the function responsible for pulling apart and putting back together the sentence, updateWords. There is one simple fix to this, changing from



                const updateWords = wordFn => sentence => sentence.split(/s+/).map(wordFn).join(' ')


                to



                const updateWords = wordFn => sentence => sentence.split(' ').map(wordFn).join(' ')


                but we might be better off using a variant of the answer from CertainPerformance, and rewriting it like this:



                const updateWords = wordFn => sentence => sentence.replace(/w+/g, wordFn)


                This fixes the bug and actually handles more cases than we could have originally. (Note that it now deals with punctuation characters as well):



                spinWords('Hey, fellow warriors!') //=> 'Hey, wollef sroirraw!'


                The important point is that in order to fix our bug, we were able to isolate the function responsible and change it without changing anything else.



                Working code



                This is what we have arrived at:






                const updateWords = wordFn => sentence => sentence.replace(/w+/g, wordFn)
                const reverseWord = word => word.split('').reverse().join('')
                const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word

                const spinWords = updateWords(reverseIfGte5)

                console.log(spinWords('Hey, fellow warriors!'))





                We have broken the problem down into two fairly reusable functions (reverseWord and updateWords), and two very specific to our problem (reverseIfGte5 and spinWords.) Each has a well-defined responsibility, and they are easy to test in isolation.



                Extending further



                This is as far as I would likely go with such a function. But because my personal library often includes a function, when, which is already a generalization of one of these, sometimes I might prefer to build on that:



                const when = (cond, then) => val => cond(val) ? then(val) : val
                const reverseIfGte5 = when(word => word.length >= 5, reverseWord)


                I created when because there are times when I want to use an altered version of my input if some condition is true about it and use it unaltered if the condition is false. That is exactly what reverseIfGte5 needs to do, so it's useful to build it on top of when.



                This is how utility libraries are built. Several specific problems have obvious connections and more general solutions to them are written to handle them. If these such solutions are generic enough, they are candidates for inclusion in your personal library or your team's library. And if they are useful to a wider audience, they might get included in a general-purpose utility library.



                I'm one of the authors of Ramda, a utility library for functional programming in JS, and this is exactly how it has been built.






                share|improve this answer




























                  0












                  0








                  0







                  Below is a discussion about a possible way to approach this problem. It is not what I would likely do for a question as simple as this, but it demonstrates a mindset that makes it easier to solve many problems, and to reuse your work as you do so.





                  Breaking the problem down



                  You want to do several things here, so it might help to break the problem down into steps.



                  At the core, you want to reverse certain words. So why not write a function to do only that? It should be simple. Here is one version:



                  const reverseWord = word => word.split('').reverse().join('')
                  reverseWord('word') //=> 'drow'


                  But you only want to do this to words whose length is at least five. Rather than rewriting our existing function, we can use it to write the more complex one:



                  const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word
                  reverseIfGte5('word') //=> 'word'
                  reverseIfGte5('supercalifragilisticexpialidocious')
                  //=> 'suoicodilaipxecitsiligarfilacrepus')


                  Note that here, we write reverseIfGte5 using reverseWord. So our reverseWord function is also available to be reused if we choose, but also so that each function is doing something simple.



                  We could now write spinWord in terms of this function, via



                  const spinWords = sentence => sentence.split(/s+/).map(reverseIfGte5).join(' ')

                  spinWords('Hey fellow warriors') //=> 'Hey wollef sroirraw'


                  This does what's expected. And it might be a good place to stop. However...



                  Do only one thing per function



                  Our spinWords function above is responsible for two things:




                  • finding the words in the sentence

                  • applying our reversing function to each


                  Ideally, a function should be responsible for one thing an one thing only. (There is some judgment to be made in deciding how such responsibilities break down, of course.)



                  It might be useful to break this apart. We can do that in different ways. Here's a simple one:



                  const updateWords = wordFn => sentence => sentence.split(/s+/).map(wordFn).join(' ')
                  const spinWords = updateWords(reverseIfGte5)


                  Now we have a reusable function, which we could use, for instance, with an obvious capitalizeFirstLetter function like this:



                  const titleCase = updateWords(capitalizeFirstLetter)
                  titleCase('Hey fellow warriors') //=> 'Hey Fellow Warriors')


                  Fixing bugs



                  Our code now looks like this:



                  const updateWords = wordFn => sentence => sentence.split(/s+/).map(wordFn).join(' ')
                  const reverseWord = word => word.split('').reverse().join('')
                  const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word
                  const spinWords = updateWords(reverseIfGte5)


                  These functions are ordered from the most likely to the least likely to be reusable.



                  Note that the total code here, when using such reusable functions, is a bit longer than this plain version:



                  const spinWords = sentence => sentence.split(/s+/).map(
                  word => word.length >= 5 ? word.split('').reverse().join('') : word
                  ).join(' ')


                  But our version has several advantages. Obviously, reusability is one. But another is that with the problem broken down into small pieces, if we find a problem, we know where look to for a solution.



                  And guess what, there is in fact a potential bug in this solution.



                  If we call this function with 'Hey fellow warriors', we return 'Hey wollef oirraw' instead of the expected 'Hey wollef sroirraw'. Our spacing is off.



                  Because this problem is broken down into distinct functions, there is no question about which function we need to change in order to fix this. Clearly it is the function responsible for pulling apart and putting back together the sentence, updateWords. There is one simple fix to this, changing from



                  const updateWords = wordFn => sentence => sentence.split(/s+/).map(wordFn).join(' ')


                  to



                  const updateWords = wordFn => sentence => sentence.split(' ').map(wordFn).join(' ')


                  but we might be better off using a variant of the answer from CertainPerformance, and rewriting it like this:



                  const updateWords = wordFn => sentence => sentence.replace(/w+/g, wordFn)


                  This fixes the bug and actually handles more cases than we could have originally. (Note that it now deals with punctuation characters as well):



                  spinWords('Hey, fellow warriors!') //=> 'Hey, wollef sroirraw!'


                  The important point is that in order to fix our bug, we were able to isolate the function responsible and change it without changing anything else.



                  Working code



                  This is what we have arrived at:






                  const updateWords = wordFn => sentence => sentence.replace(/w+/g, wordFn)
                  const reverseWord = word => word.split('').reverse().join('')
                  const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word

                  const spinWords = updateWords(reverseIfGte5)

                  console.log(spinWords('Hey, fellow warriors!'))





                  We have broken the problem down into two fairly reusable functions (reverseWord and updateWords), and two very specific to our problem (reverseIfGte5 and spinWords.) Each has a well-defined responsibility, and they are easy to test in isolation.



                  Extending further



                  This is as far as I would likely go with such a function. But because my personal library often includes a function, when, which is already a generalization of one of these, sometimes I might prefer to build on that:



                  const when = (cond, then) => val => cond(val) ? then(val) : val
                  const reverseIfGte5 = when(word => word.length >= 5, reverseWord)


                  I created when because there are times when I want to use an altered version of my input if some condition is true about it and use it unaltered if the condition is false. That is exactly what reverseIfGte5 needs to do, so it's useful to build it on top of when.



                  This is how utility libraries are built. Several specific problems have obvious connections and more general solutions to them are written to handle them. If these such solutions are generic enough, they are candidates for inclusion in your personal library or your team's library. And if they are useful to a wider audience, they might get included in a general-purpose utility library.



                  I'm one of the authors of Ramda, a utility library for functional programming in JS, and this is exactly how it has been built.






                  share|improve this answer















                  Below is a discussion about a possible way to approach this problem. It is not what I would likely do for a question as simple as this, but it demonstrates a mindset that makes it easier to solve many problems, and to reuse your work as you do so.





                  Breaking the problem down



                  You want to do several things here, so it might help to break the problem down into steps.



                  At the core, you want to reverse certain words. So why not write a function to do only that? It should be simple. Here is one version:



                  const reverseWord = word => word.split('').reverse().join('')
                  reverseWord('word') //=> 'drow'


                  But you only want to do this to words whose length is at least five. Rather than rewriting our existing function, we can use it to write the more complex one:



                  const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word
                  reverseIfGte5('word') //=> 'word'
                  reverseIfGte5('supercalifragilisticexpialidocious')
                  //=> 'suoicodilaipxecitsiligarfilacrepus')


                  Note that here, we write reverseIfGte5 using reverseWord. So our reverseWord function is also available to be reused if we choose, but also so that each function is doing something simple.



                  We could now write spinWord in terms of this function, via



                  const spinWords = sentence => sentence.split(/s+/).map(reverseIfGte5).join(' ')

                  spinWords('Hey fellow warriors') //=> 'Hey wollef sroirraw'


                  This does what's expected. And it might be a good place to stop. However...



                  Do only one thing per function



                  Our spinWords function above is responsible for two things:




                  • finding the words in the sentence

                  • applying our reversing function to each


                  Ideally, a function should be responsible for one thing an one thing only. (There is some judgment to be made in deciding how such responsibilities break down, of course.)



                  It might be useful to break this apart. We can do that in different ways. Here's a simple one:



                  const updateWords = wordFn => sentence => sentence.split(/s+/).map(wordFn).join(' ')
                  const spinWords = updateWords(reverseIfGte5)


                  Now we have a reusable function, which we could use, for instance, with an obvious capitalizeFirstLetter function like this:



                  const titleCase = updateWords(capitalizeFirstLetter)
                  titleCase('Hey fellow warriors') //=> 'Hey Fellow Warriors')


                  Fixing bugs



                  Our code now looks like this:



                  const updateWords = wordFn => sentence => sentence.split(/s+/).map(wordFn).join(' ')
                  const reverseWord = word => word.split('').reverse().join('')
                  const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word
                  const spinWords = updateWords(reverseIfGte5)


                  These functions are ordered from the most likely to the least likely to be reusable.



                  Note that the total code here, when using such reusable functions, is a bit longer than this plain version:



                  const spinWords = sentence => sentence.split(/s+/).map(
                  word => word.length >= 5 ? word.split('').reverse().join('') : word
                  ).join(' ')


                  But our version has several advantages. Obviously, reusability is one. But another is that with the problem broken down into small pieces, if we find a problem, we know where look to for a solution.



                  And guess what, there is in fact a potential bug in this solution.



                  If we call this function with 'Hey fellow warriors', we return 'Hey wollef oirraw' instead of the expected 'Hey wollef sroirraw'. Our spacing is off.



                  Because this problem is broken down into distinct functions, there is no question about which function we need to change in order to fix this. Clearly it is the function responsible for pulling apart and putting back together the sentence, updateWords. There is one simple fix to this, changing from



                  const updateWords = wordFn => sentence => sentence.split(/s+/).map(wordFn).join(' ')


                  to



                  const updateWords = wordFn => sentence => sentence.split(' ').map(wordFn).join(' ')


                  but we might be better off using a variant of the answer from CertainPerformance, and rewriting it like this:



                  const updateWords = wordFn => sentence => sentence.replace(/w+/g, wordFn)


                  This fixes the bug and actually handles more cases than we could have originally. (Note that it now deals with punctuation characters as well):



                  spinWords('Hey, fellow warriors!') //=> 'Hey, wollef sroirraw!'


                  The important point is that in order to fix our bug, we were able to isolate the function responsible and change it without changing anything else.



                  Working code



                  This is what we have arrived at:






                  const updateWords = wordFn => sentence => sentence.replace(/w+/g, wordFn)
                  const reverseWord = word => word.split('').reverse().join('')
                  const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word

                  const spinWords = updateWords(reverseIfGte5)

                  console.log(spinWords('Hey, fellow warriors!'))





                  We have broken the problem down into two fairly reusable functions (reverseWord and updateWords), and two very specific to our problem (reverseIfGte5 and spinWords.) Each has a well-defined responsibility, and they are easy to test in isolation.



                  Extending further



                  This is as far as I would likely go with such a function. But because my personal library often includes a function, when, which is already a generalization of one of these, sometimes I might prefer to build on that:



                  const when = (cond, then) => val => cond(val) ? then(val) : val
                  const reverseIfGte5 = when(word => word.length >= 5, reverseWord)


                  I created when because there are times when I want to use an altered version of my input if some condition is true about it and use it unaltered if the condition is false. That is exactly what reverseIfGte5 needs to do, so it's useful to build it on top of when.



                  This is how utility libraries are built. Several specific problems have obvious connections and more general solutions to them are written to handle them. If these such solutions are generic enough, they are candidates for inclusion in your personal library or your team's library. And if they are useful to a wider audience, they might get included in a general-purpose utility library.



                  I'm one of the authors of Ramda, a utility library for functional programming in JS, and this is exactly how it has been built.






                  const updateWords = wordFn => sentence => sentence.replace(/w+/g, wordFn)
                  const reverseWord = word => word.split('').reverse().join('')
                  const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word

                  const spinWords = updateWords(reverseIfGte5)

                  console.log(spinWords('Hey, fellow warriors!'))





                  const updateWords = wordFn => sentence => sentence.replace(/w+/g, wordFn)
                  const reverseWord = word => word.split('').reverse().join('')
                  const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word

                  const spinWords = updateWords(reverseIfGte5)

                  console.log(spinWords('Hey, fellow warriors!'))






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Jan 1 at 21:22

























                  answered Dec 31 '18 at 3:16









                  Scott SauyetScott Sauyet

                  21k22757




                  21k22757






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53982133%2ftaking-a-string-and-reversing-certain-words-javascript%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      MongoDB - Not Authorized To Execute Command

                      in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith

                      Npm cannot find a required file even through it is in the searched directory