How to remove several different stems at the end of the word using slicing












0















Although I understand there are tools such as NLTK to do this for me, however, I would like to understand how I can slice several stems within a list efficiently.



Say my list of words is;



list = ["another", "cats", "walrus", "relaxed", "annoyingly", "rest", "normal", "hopping", "classes", "wing", "feed"]


And my common stems I would like to remove may be;



stems = ["s", "es", "ed", "est", "ing", "ly"] etc


With words I do not want stemmed specified as;



noStem = ["walrus", "rest", "wing", "feed"]


I have worked out how to do it for one specific stem like "s". For example, my code would be;



for eachWord in list:
if eachWord not in noStem:
if eachWord[-1] == "s":
eachWord = eachWord[:-1]

stemmedList = stemmedList + [eachWord]


I am not sure how I would apply this to all my stems in a more efficient way.



Thanks for your help and advice!










share|improve this question



























    0















    Although I understand there are tools such as NLTK to do this for me, however, I would like to understand how I can slice several stems within a list efficiently.



    Say my list of words is;



    list = ["another", "cats", "walrus", "relaxed", "annoyingly", "rest", "normal", "hopping", "classes", "wing", "feed"]


    And my common stems I would like to remove may be;



    stems = ["s", "es", "ed", "est", "ing", "ly"] etc


    With words I do not want stemmed specified as;



    noStem = ["walrus", "rest", "wing", "feed"]


    I have worked out how to do it for one specific stem like "s". For example, my code would be;



    for eachWord in list:
    if eachWord not in noStem:
    if eachWord[-1] == "s":
    eachWord = eachWord[:-1]

    stemmedList = stemmedList + [eachWord]


    I am not sure how I would apply this to all my stems in a more efficient way.



    Thanks for your help and advice!










    share|improve this question

























      0












      0








      0








      Although I understand there are tools such as NLTK to do this for me, however, I would like to understand how I can slice several stems within a list efficiently.



      Say my list of words is;



      list = ["another", "cats", "walrus", "relaxed", "annoyingly", "rest", "normal", "hopping", "classes", "wing", "feed"]


      And my common stems I would like to remove may be;



      stems = ["s", "es", "ed", "est", "ing", "ly"] etc


      With words I do not want stemmed specified as;



      noStem = ["walrus", "rest", "wing", "feed"]


      I have worked out how to do it for one specific stem like "s". For example, my code would be;



      for eachWord in list:
      if eachWord not in noStem:
      if eachWord[-1] == "s":
      eachWord = eachWord[:-1]

      stemmedList = stemmedList + [eachWord]


      I am not sure how I would apply this to all my stems in a more efficient way.



      Thanks for your help and advice!










      share|improve this question














      Although I understand there are tools such as NLTK to do this for me, however, I would like to understand how I can slice several stems within a list efficiently.



      Say my list of words is;



      list = ["another", "cats", "walrus", "relaxed", "annoyingly", "rest", "normal", "hopping", "classes", "wing", "feed"]


      And my common stems I would like to remove may be;



      stems = ["s", "es", "ed", "est", "ing", "ly"] etc


      With words I do not want stemmed specified as;



      noStem = ["walrus", "rest", "wing", "feed"]


      I have worked out how to do it for one specific stem like "s". For example, my code would be;



      for eachWord in list:
      if eachWord not in noStem:
      if eachWord[-1] == "s":
      eachWord = eachWord[:-1]

      stemmedList = stemmedList + [eachWord]


      I am not sure how I would apply this to all my stems in a more efficient way.



      Thanks for your help and advice!







      python






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 21 '18 at 19:32









      highfocushighfocus

      62




      62
























          3 Answers
          3






          active

          oldest

          votes


















          0














          I would suggest you convert noStem to a set so that the check if eachWord not in noStem is fast. Then you can check if the word endswith any stem in stems. If it does, you can use the largest stem that matches and remove it from the word:



          lst = ["another", "cats", "walrus", "relaxed", "annoyingly", "rest", "normal", "hopping", "classes", "wing", "feed"]
          stems = ["s", "es", "ed", "est", "ing", "ly"]
          noStem = {"walrus", "rest", "wing", "feed"}
          stemmedList =

          for word in lst:
          if word in noStem or not any([word.endswith(stem) for stem in stems]):
          stemmedList.append(word)
          else:
          stem = max([s for s in stems if word.endswith(s)], key=len)
          stemmedList.append(word[:len(word) - len(stem)])

          print(stemmedList)
          # ['another', 'cat', 'walrus', 'relax', 'annoying', 'rest', 'normal', 'hopp', 'class', 'wing', 'feed']





          share|improve this answer

































            0














            It's much more complicated than this but here goes a starter code using much faster pandas module. Here it goes.



            import pandas as pd
            import re

            word_list = ["another", "cats", "walrus", "relaxed", "annoyingly", "rest", "normal", "hopping", "classes", "wing", "feed"]

            stems = ["es", "ed", "est", "ing", "ly", "s"]

            # a set for quick lookup
            noStem = set(["walrus", "rest", "wing", "feed"])

            # build series
            words = pd.Series(word_list)

            # filter out words in noStem
            words = words[words.apply(lambda x: x not in noStem)]

            # compile regular explession - performance - join all stems for matching
            term_matching = '|'.join(stems)
            expr = re.compile(r'(.+?)({})$'.format(term_matching))

            df = words.str.extract(expr, expand=True)
            df.dropna(how='any', inplace=True)
            df.columns = ['words', 'stems']

            stemmed_list = df.words.tolist()


            I hope it helps ...






            share|improve this answer































              0














              I think that isn't a bad start. You just need to add the second loop to be able to work with multiple endings. You can try something like below, (You'll notice I've renamed the variable list because it's dangerous having variables shadowing built-in names)



              stemmed_list = 
              for word in word_list:
              if word not in noStem:
              for ending in stems:
              if word.endswith(ending):
              word = word[:-len(ending)]
              break # This will prevent iterating over all endings once match is found
              stemmed_list.append(word)


              Or if as per your comment you don't want to use endswith



              stemmed_list = 
              for word in word_list:
              if word not in noStem:
              for ending in stems:
              if word[-len(ending):] == ending:
              word = word[:-len(ending)]
              break # This will prevent iterating over all endings once match is found
              stemmed_list.append(word)





              share|improve this answer


























              • Thank you for this comment, this is the idea I was aiming for. If I may ask a second question, is it possible to do this without the endswith() method? I'd like to use a slice constructor to make this work.

                – highfocus
                Nov 22 '18 at 9:14











              • @highfocus that is possible (see my edit) although I don't necessarily know why you would want to as endswith is a nice built-in convenience method

                – Sven Harris
                Nov 22 '18 at 9:49











              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%2f53419322%2fhow-to-remove-several-different-stems-at-the-end-of-the-word-using-slicing%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              3 Answers
              3






              active

              oldest

              votes








              3 Answers
              3






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              0














              I would suggest you convert noStem to a set so that the check if eachWord not in noStem is fast. Then you can check if the word endswith any stem in stems. If it does, you can use the largest stem that matches and remove it from the word:



              lst = ["another", "cats", "walrus", "relaxed", "annoyingly", "rest", "normal", "hopping", "classes", "wing", "feed"]
              stems = ["s", "es", "ed", "est", "ing", "ly"]
              noStem = {"walrus", "rest", "wing", "feed"}
              stemmedList =

              for word in lst:
              if word in noStem or not any([word.endswith(stem) for stem in stems]):
              stemmedList.append(word)
              else:
              stem = max([s for s in stems if word.endswith(s)], key=len)
              stemmedList.append(word[:len(word) - len(stem)])

              print(stemmedList)
              # ['another', 'cat', 'walrus', 'relax', 'annoying', 'rest', 'normal', 'hopp', 'class', 'wing', 'feed']





              share|improve this answer






























                0














                I would suggest you convert noStem to a set so that the check if eachWord not in noStem is fast. Then you can check if the word endswith any stem in stems. If it does, you can use the largest stem that matches and remove it from the word:



                lst = ["another", "cats", "walrus", "relaxed", "annoyingly", "rest", "normal", "hopping", "classes", "wing", "feed"]
                stems = ["s", "es", "ed", "est", "ing", "ly"]
                noStem = {"walrus", "rest", "wing", "feed"}
                stemmedList =

                for word in lst:
                if word in noStem or not any([word.endswith(stem) for stem in stems]):
                stemmedList.append(word)
                else:
                stem = max([s for s in stems if word.endswith(s)], key=len)
                stemmedList.append(word[:len(word) - len(stem)])

                print(stemmedList)
                # ['another', 'cat', 'walrus', 'relax', 'annoying', 'rest', 'normal', 'hopp', 'class', 'wing', 'feed']





                share|improve this answer




























                  0












                  0








                  0







                  I would suggest you convert noStem to a set so that the check if eachWord not in noStem is fast. Then you can check if the word endswith any stem in stems. If it does, you can use the largest stem that matches and remove it from the word:



                  lst = ["another", "cats", "walrus", "relaxed", "annoyingly", "rest", "normal", "hopping", "classes", "wing", "feed"]
                  stems = ["s", "es", "ed", "est", "ing", "ly"]
                  noStem = {"walrus", "rest", "wing", "feed"}
                  stemmedList =

                  for word in lst:
                  if word in noStem or not any([word.endswith(stem) for stem in stems]):
                  stemmedList.append(word)
                  else:
                  stem = max([s for s in stems if word.endswith(s)], key=len)
                  stemmedList.append(word[:len(word) - len(stem)])

                  print(stemmedList)
                  # ['another', 'cat', 'walrus', 'relax', 'annoying', 'rest', 'normal', 'hopp', 'class', 'wing', 'feed']





                  share|improve this answer















                  I would suggest you convert noStem to a set so that the check if eachWord not in noStem is fast. Then you can check if the word endswith any stem in stems. If it does, you can use the largest stem that matches and remove it from the word:



                  lst = ["another", "cats", "walrus", "relaxed", "annoyingly", "rest", "normal", "hopping", "classes", "wing", "feed"]
                  stems = ["s", "es", "ed", "est", "ing", "ly"]
                  noStem = {"walrus", "rest", "wing", "feed"}
                  stemmedList =

                  for word in lst:
                  if word in noStem or not any([word.endswith(stem) for stem in stems]):
                  stemmedList.append(word)
                  else:
                  stem = max([s for s in stems if word.endswith(s)], key=len)
                  stemmedList.append(word[:len(word) - len(stem)])

                  print(stemmedList)
                  # ['another', 'cat', 'walrus', 'relax', 'annoying', 'rest', 'normal', 'hopp', 'class', 'wing', 'feed']






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 21 '18 at 19:54

























                  answered Nov 21 '18 at 19:41









                  sliderslider

                  8,55811331




                  8,55811331

























                      0














                      It's much more complicated than this but here goes a starter code using much faster pandas module. Here it goes.



                      import pandas as pd
                      import re

                      word_list = ["another", "cats", "walrus", "relaxed", "annoyingly", "rest", "normal", "hopping", "classes", "wing", "feed"]

                      stems = ["es", "ed", "est", "ing", "ly", "s"]

                      # a set for quick lookup
                      noStem = set(["walrus", "rest", "wing", "feed"])

                      # build series
                      words = pd.Series(word_list)

                      # filter out words in noStem
                      words = words[words.apply(lambda x: x not in noStem)]

                      # compile regular explession - performance - join all stems for matching
                      term_matching = '|'.join(stems)
                      expr = re.compile(r'(.+?)({})$'.format(term_matching))

                      df = words.str.extract(expr, expand=True)
                      df.dropna(how='any', inplace=True)
                      df.columns = ['words', 'stems']

                      stemmed_list = df.words.tolist()


                      I hope it helps ...






                      share|improve this answer




























                        0














                        It's much more complicated than this but here goes a starter code using much faster pandas module. Here it goes.



                        import pandas as pd
                        import re

                        word_list = ["another", "cats", "walrus", "relaxed", "annoyingly", "rest", "normal", "hopping", "classes", "wing", "feed"]

                        stems = ["es", "ed", "est", "ing", "ly", "s"]

                        # a set for quick lookup
                        noStem = set(["walrus", "rest", "wing", "feed"])

                        # build series
                        words = pd.Series(word_list)

                        # filter out words in noStem
                        words = words[words.apply(lambda x: x not in noStem)]

                        # compile regular explession - performance - join all stems for matching
                        term_matching = '|'.join(stems)
                        expr = re.compile(r'(.+?)({})$'.format(term_matching))

                        df = words.str.extract(expr, expand=True)
                        df.dropna(how='any', inplace=True)
                        df.columns = ['words', 'stems']

                        stemmed_list = df.words.tolist()


                        I hope it helps ...






                        share|improve this answer


























                          0












                          0








                          0







                          It's much more complicated than this but here goes a starter code using much faster pandas module. Here it goes.



                          import pandas as pd
                          import re

                          word_list = ["another", "cats", "walrus", "relaxed", "annoyingly", "rest", "normal", "hopping", "classes", "wing", "feed"]

                          stems = ["es", "ed", "est", "ing", "ly", "s"]

                          # a set for quick lookup
                          noStem = set(["walrus", "rest", "wing", "feed"])

                          # build series
                          words = pd.Series(word_list)

                          # filter out words in noStem
                          words = words[words.apply(lambda x: x not in noStem)]

                          # compile regular explession - performance - join all stems for matching
                          term_matching = '|'.join(stems)
                          expr = re.compile(r'(.+?)({})$'.format(term_matching))

                          df = words.str.extract(expr, expand=True)
                          df.dropna(how='any', inplace=True)
                          df.columns = ['words', 'stems']

                          stemmed_list = df.words.tolist()


                          I hope it helps ...






                          share|improve this answer













                          It's much more complicated than this but here goes a starter code using much faster pandas module. Here it goes.



                          import pandas as pd
                          import re

                          word_list = ["another", "cats", "walrus", "relaxed", "annoyingly", "rest", "normal", "hopping", "classes", "wing", "feed"]

                          stems = ["es", "ed", "est", "ing", "ly", "s"]

                          # a set for quick lookup
                          noStem = set(["walrus", "rest", "wing", "feed"])

                          # build series
                          words = pd.Series(word_list)

                          # filter out words in noStem
                          words = words[words.apply(lambda x: x not in noStem)]

                          # compile regular explession - performance - join all stems for matching
                          term_matching = '|'.join(stems)
                          expr = re.compile(r'(.+?)({})$'.format(term_matching))

                          df = words.str.extract(expr, expand=True)
                          df.dropna(how='any', inplace=True)
                          df.columns = ['words', 'stems']

                          stemmed_list = df.words.tolist()


                          I hope it helps ...







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Nov 21 '18 at 21:50









                          AResemAResem

                          1114




                          1114























                              0














                              I think that isn't a bad start. You just need to add the second loop to be able to work with multiple endings. You can try something like below, (You'll notice I've renamed the variable list because it's dangerous having variables shadowing built-in names)



                              stemmed_list = 
                              for word in word_list:
                              if word not in noStem:
                              for ending in stems:
                              if word.endswith(ending):
                              word = word[:-len(ending)]
                              break # This will prevent iterating over all endings once match is found
                              stemmed_list.append(word)


                              Or if as per your comment you don't want to use endswith



                              stemmed_list = 
                              for word in word_list:
                              if word not in noStem:
                              for ending in stems:
                              if word[-len(ending):] == ending:
                              word = word[:-len(ending)]
                              break # This will prevent iterating over all endings once match is found
                              stemmed_list.append(word)





                              share|improve this answer


























                              • Thank you for this comment, this is the idea I was aiming for. If I may ask a second question, is it possible to do this without the endswith() method? I'd like to use a slice constructor to make this work.

                                – highfocus
                                Nov 22 '18 at 9:14











                              • @highfocus that is possible (see my edit) although I don't necessarily know why you would want to as endswith is a nice built-in convenience method

                                – Sven Harris
                                Nov 22 '18 at 9:49
















                              0














                              I think that isn't a bad start. You just need to add the second loop to be able to work with multiple endings. You can try something like below, (You'll notice I've renamed the variable list because it's dangerous having variables shadowing built-in names)



                              stemmed_list = 
                              for word in word_list:
                              if word not in noStem:
                              for ending in stems:
                              if word.endswith(ending):
                              word = word[:-len(ending)]
                              break # This will prevent iterating over all endings once match is found
                              stemmed_list.append(word)


                              Or if as per your comment you don't want to use endswith



                              stemmed_list = 
                              for word in word_list:
                              if word not in noStem:
                              for ending in stems:
                              if word[-len(ending):] == ending:
                              word = word[:-len(ending)]
                              break # This will prevent iterating over all endings once match is found
                              stemmed_list.append(word)





                              share|improve this answer


























                              • Thank you for this comment, this is the idea I was aiming for. If I may ask a second question, is it possible to do this without the endswith() method? I'd like to use a slice constructor to make this work.

                                – highfocus
                                Nov 22 '18 at 9:14











                              • @highfocus that is possible (see my edit) although I don't necessarily know why you would want to as endswith is a nice built-in convenience method

                                – Sven Harris
                                Nov 22 '18 at 9:49














                              0












                              0








                              0







                              I think that isn't a bad start. You just need to add the second loop to be able to work with multiple endings. You can try something like below, (You'll notice I've renamed the variable list because it's dangerous having variables shadowing built-in names)



                              stemmed_list = 
                              for word in word_list:
                              if word not in noStem:
                              for ending in stems:
                              if word.endswith(ending):
                              word = word[:-len(ending)]
                              break # This will prevent iterating over all endings once match is found
                              stemmed_list.append(word)


                              Or if as per your comment you don't want to use endswith



                              stemmed_list = 
                              for word in word_list:
                              if word not in noStem:
                              for ending in stems:
                              if word[-len(ending):] == ending:
                              word = word[:-len(ending)]
                              break # This will prevent iterating over all endings once match is found
                              stemmed_list.append(word)





                              share|improve this answer















                              I think that isn't a bad start. You just need to add the second loop to be able to work with multiple endings. You can try something like below, (You'll notice I've renamed the variable list because it's dangerous having variables shadowing built-in names)



                              stemmed_list = 
                              for word in word_list:
                              if word not in noStem:
                              for ending in stems:
                              if word.endswith(ending):
                              word = word[:-len(ending)]
                              break # This will prevent iterating over all endings once match is found
                              stemmed_list.append(word)


                              Or if as per your comment you don't want to use endswith



                              stemmed_list = 
                              for word in word_list:
                              if word not in noStem:
                              for ending in stems:
                              if word[-len(ending):] == ending:
                              word = word[:-len(ending)]
                              break # This will prevent iterating over all endings once match is found
                              stemmed_list.append(word)






                              share|improve this answer














                              share|improve this answer



                              share|improve this answer








                              edited Nov 22 '18 at 9:47

























                              answered Nov 21 '18 at 19:53









                              Sven HarrisSven Harris

                              2,1861516




                              2,1861516













                              • Thank you for this comment, this is the idea I was aiming for. If I may ask a second question, is it possible to do this without the endswith() method? I'd like to use a slice constructor to make this work.

                                – highfocus
                                Nov 22 '18 at 9:14











                              • @highfocus that is possible (see my edit) although I don't necessarily know why you would want to as endswith is a nice built-in convenience method

                                – Sven Harris
                                Nov 22 '18 at 9:49



















                              • Thank you for this comment, this is the idea I was aiming for. If I may ask a second question, is it possible to do this without the endswith() method? I'd like to use a slice constructor to make this work.

                                – highfocus
                                Nov 22 '18 at 9:14











                              • @highfocus that is possible (see my edit) although I don't necessarily know why you would want to as endswith is a nice built-in convenience method

                                – Sven Harris
                                Nov 22 '18 at 9:49

















                              Thank you for this comment, this is the idea I was aiming for. If I may ask a second question, is it possible to do this without the endswith() method? I'd like to use a slice constructor to make this work.

                              – highfocus
                              Nov 22 '18 at 9:14





                              Thank you for this comment, this is the idea I was aiming for. If I may ask a second question, is it possible to do this without the endswith() method? I'd like to use a slice constructor to make this work.

                              – highfocus
                              Nov 22 '18 at 9:14













                              @highfocus that is possible (see my edit) although I don't necessarily know why you would want to as endswith is a nice built-in convenience method

                              – Sven Harris
                              Nov 22 '18 at 9:49





                              @highfocus that is possible (see my edit) although I don't necessarily know why you would want to as endswith is a nice built-in convenience method

                              – Sven Harris
                              Nov 22 '18 at 9:49


















                              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%2f53419322%2fhow-to-remove-several-different-stems-at-the-end-of-the-word-using-slicing%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

                              Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

                              ComboBox Display Member on multiple fields

                              Is it possible to collect Nectar points via Trainline?