Calculate Levenshtein distance between two strings in Python The 2019 Stack Overflow Developer Survey Results Are In Unicorn Meta Zoo #1: Why another podcast? Announcing the arrival of Valued Associate #679: Cesar ManaraEdit Distance Between Two StringsString Matching and ClusteringSorting movie search results by similarityEdit distance between 2 stringsMaking the Levenshtein distance code cleanerEdit distance (Optimal Alignment) - follow upGet Levenshtein DistanceMessage classification with Levenshtein DistanceCode to implement the Jaro similarity for fuzzy matching stringsFinding differences in strings with Levenshtein distance and soundex

Is this wall load bearing? Blueprints and photos attached

What to do when moving next to a bird sanctuary with a loosely-domesticated cat?

Can each chord in a progression create its own key?

Variable with quotation marks "$()"

The following signatures were invalid: EXPKEYSIG 1397BC53640DB551

Presidential Pardon

Button changing its text & action. Good or terrible?

How to determine omitted units in a publication

Is every episode of "Where are my Pants?" identical?

How to read αἱμύλιος or when to aspirate

Does Parliament hold absolute power in the UK?

What was the last x86 CPU that did not have the x87 floating-point unit built in?

Sub-subscripts in strings cause different spacings than subscripts

How do I design a circuit to convert a 100 mV and 50 Hz sine wave to a square wave?

Is it ethical to upload a automatically generated paper to a non peer-reviewed site as part of a larger research?

Loose spokes after only a few rides

Student Loan from years ago pops up and is taking my salary

Is there a writing software that you can sort scenes like slides in PowerPoint?

Windows 10: How to Lock (not sleep) laptop on lid close?

Why are PDP-7-style microprogrammed instructions out of vogue?

How to politely respond to generic emails requesting a PhD/job in my lab? Without wasting too much time

Do I have Disadvantage attacking with an off-hand weapon?

Why doesn't shell automatically fix "useless use of cat"?

Match Roman Numerals



Calculate Levenshtein distance between two strings in Python



The 2019 Stack Overflow Developer Survey Results Are In
Unicorn Meta Zoo #1: Why another podcast?
Announcing the arrival of Valued Associate #679: Cesar ManaraEdit Distance Between Two StringsString Matching and ClusteringSorting movie search results by similarityEdit distance between 2 stringsMaking the Levenshtein distance code cleanerEdit distance (Optimal Alignment) - follow upGet Levenshtein DistanceMessage classification with Levenshtein DistanceCode to implement the Jaro similarity for fuzzy matching stringsFinding differences in strings with Levenshtein distance and soundex



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








11












$begingroup$


I need a function that checks how different are two different strings. I chose the Levenshtein distance as a quick approach, and implemented this function:



from difflib import ndiff

def calculate_levenshtein_distance(str_1, str_2):
"""
The Levenshtein distance is a string metric for measuring the difference between two sequences.
It is calculated as the minimum number of single-character edits necessary to transform one string into another
"""
distance = 0
buffer_removed = buffer_added = 0
for x in ndiff(str_1, str_2):
code = x[0]
# Code ? is ignored as it does not translate to any modification
if code == ' ':
distance += max(buffer_removed, buffer_added)
buffer_removed = buffer_added = 0
elif code == '-':
buffer_removed += 1
elif code == '+':
buffer_added += 1
distance += max(buffer_removed, buffer_added)
return distance


Then calling it as:



similarity = 1 - calculate_levenshtein_distance(str_1, str_2) / max(len(str_1), len(str_2))


How sloppy/prone to errors is this code? How can it be improved?










share|improve this question









New contributor




Kyra_W is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$


















    11












    $begingroup$


    I need a function that checks how different are two different strings. I chose the Levenshtein distance as a quick approach, and implemented this function:



    from difflib import ndiff

    def calculate_levenshtein_distance(str_1, str_2):
    """
    The Levenshtein distance is a string metric for measuring the difference between two sequences.
    It is calculated as the minimum number of single-character edits necessary to transform one string into another
    """
    distance = 0
    buffer_removed = buffer_added = 0
    for x in ndiff(str_1, str_2):
    code = x[0]
    # Code ? is ignored as it does not translate to any modification
    if code == ' ':
    distance += max(buffer_removed, buffer_added)
    buffer_removed = buffer_added = 0
    elif code == '-':
    buffer_removed += 1
    elif code == '+':
    buffer_added += 1
    distance += max(buffer_removed, buffer_added)
    return distance


    Then calling it as:



    similarity = 1 - calculate_levenshtein_distance(str_1, str_2) / max(len(str_1), len(str_2))


    How sloppy/prone to errors is this code? How can it be improved?










    share|improve this question









    New contributor




    Kyra_W is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.







    $endgroup$














      11












      11








      11


      2



      $begingroup$


      I need a function that checks how different are two different strings. I chose the Levenshtein distance as a quick approach, and implemented this function:



      from difflib import ndiff

      def calculate_levenshtein_distance(str_1, str_2):
      """
      The Levenshtein distance is a string metric for measuring the difference between two sequences.
      It is calculated as the minimum number of single-character edits necessary to transform one string into another
      """
      distance = 0
      buffer_removed = buffer_added = 0
      for x in ndiff(str_1, str_2):
      code = x[0]
      # Code ? is ignored as it does not translate to any modification
      if code == ' ':
      distance += max(buffer_removed, buffer_added)
      buffer_removed = buffer_added = 0
      elif code == '-':
      buffer_removed += 1
      elif code == '+':
      buffer_added += 1
      distance += max(buffer_removed, buffer_added)
      return distance


      Then calling it as:



      similarity = 1 - calculate_levenshtein_distance(str_1, str_2) / max(len(str_1), len(str_2))


      How sloppy/prone to errors is this code? How can it be improved?










      share|improve this question









      New contributor




      Kyra_W is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.







      $endgroup$




      I need a function that checks how different are two different strings. I chose the Levenshtein distance as a quick approach, and implemented this function:



      from difflib import ndiff

      def calculate_levenshtein_distance(str_1, str_2):
      """
      The Levenshtein distance is a string metric for measuring the difference between two sequences.
      It is calculated as the minimum number of single-character edits necessary to transform one string into another
      """
      distance = 0
      buffer_removed = buffer_added = 0
      for x in ndiff(str_1, str_2):
      code = x[0]
      # Code ? is ignored as it does not translate to any modification
      if code == ' ':
      distance += max(buffer_removed, buffer_added)
      buffer_removed = buffer_added = 0
      elif code == '-':
      buffer_removed += 1
      elif code == '+':
      buffer_added += 1
      distance += max(buffer_removed, buffer_added)
      return distance


      Then calling it as:



      similarity = 1 - calculate_levenshtein_distance(str_1, str_2) / max(len(str_1), len(str_2))


      How sloppy/prone to errors is this code? How can it be improved?







      python edit-distance






      share|improve this question









      New contributor




      Kyra_W is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      Kyra_W is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited Apr 8 at 19:14









      Reinderien

      5,445927




      5,445927






      New contributor




      Kyra_W is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked Apr 8 at 10:01









      Kyra_WKyra_W

      585




      585




      New contributor




      Kyra_W is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      Kyra_W is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      Kyra_W is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.




















          2 Answers
          2






          active

          oldest

          votes


















          14












          $begingroup$

          There is a module available for exactly that calculation, python-Levenshtein. You can install it with pip install python-Levenshtein.



          It is implemented in C, so is probably faster than anything you can come up with yourself.



          from Levenshtein import distance as levenshtein_distance



          According to the docstring conventions, your docstring should look like this, i.e. with the indentation aligned to the """ and the line length curtailed to 80 characters.



          def calculate_levenshtein_distance(str_1, str_2):
          """
          The Levenshtein distance is a string metric for measuring the difference
          between two sequences.
          It is calculated as the minimum number of single-character edits necessary to
          transform one string into another.
          """
          ...





          share|improve this answer











          $endgroup$








          • 10




            $begingroup$
            Just to note the module is licensed under GPL 2.0 so watch out if you're using it for work.
            $endgroup$
            – lucasgcb
            Apr 8 at 13:08










          • $begingroup$
            Just to point out a small nitpick to other people who may stumble upon this answer, as per help center: "Every answer must make at least one insightful observation about the code in the question. Answers that merely provide an alternate solution with no explanation or justification do not constitute valid Code Review answers and may be deleted." While this answer does provide alternative and existing module suggestion, it also goes into some suggestions about improving code quality. So it's an example of a decent answer
            $endgroup$
            – Sergiy Kolodyazhnyy
            Apr 9 at 0:02










          • $begingroup$
            Thanks! I did not know of this module. Will check it out
            $endgroup$
            – Kyra_W
            Apr 9 at 8:21






          • 1




            $begingroup$
            @SergiyKolodyazhnyy While I (obviously) agree, and that is one of the reasons I added that part, I would actually argue that "It is implemented in C, so is probably faster than anything you can come up with yourself" would get around the "no explanation or justification" clause
            $endgroup$
            – Graipher
            Apr 9 at 8:21



















          9












          $begingroup$

          The code itself is rather clear. There are some smaller changes I would make



          tuple unpacking



          You can use tuple unpacking to do:



          for code, *_ in ndiff(str1, str2):


          instead of:



          for x in ndiff(str_1, str_2):
          code = x[0]


          dict results:



          Instead of a counter for the additions and removals, I would keep it in 1 dict: counter = ("+": 0, "-": 0)



          def levenshtein_distance(str1, str2, ):
          counter = "+": 0, "-": 0
          distance = 0
          for edit_code, *_ in ndiff(str1, str2):
          if edit_code == " ":
          distance += max(counter.values())
          counter = "+": 0, "-": 0
          else:
          counter[edit_code] += 1
          distance += max(counter.values())
          return distance


          generators



          A smaller, less useful variation, is to let this method be a generator, and use the builtin sum to do the summary. this saves 1 variable inside the function:



          def levenshtein_distance_gen(str1, str2, ):
          counter = "+": 0, "-": 0
          for edit_code, *_ in ndiff(str1, str2):
          if edit_code == " ":
          yield max(counter.values())
          counter = "+": 0, "-": 0
          else:
          counter[edit_code] += 1
          yield max(counter.values())

          sum(levenshtein_distance_gen(str1, str2))



          timings



          The differences in timings between the original and both these variations are minimal, and within the variation of results. This is rather logical, since for simple strings (aaabbbc and abcabcabc) 90% of the time is spent in ndiff






          share|improve this answer









          $endgroup$












          • $begingroup$
            Awesome suggestions. I had not even considered the generator approach, but it looks very nice. Thanks
            $endgroup$
            – Kyra_W
            Apr 9 at 8:24











          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: "196"
          ;
          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: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          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
          );



          );






          Kyra_W is a new contributor. Be nice, and check out our Code of Conduct.









          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f217065%2fcalculate-levenshtein-distance-between-two-strings-in-python%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









          14












          $begingroup$

          There is a module available for exactly that calculation, python-Levenshtein. You can install it with pip install python-Levenshtein.



          It is implemented in C, so is probably faster than anything you can come up with yourself.



          from Levenshtein import distance as levenshtein_distance



          According to the docstring conventions, your docstring should look like this, i.e. with the indentation aligned to the """ and the line length curtailed to 80 characters.



          def calculate_levenshtein_distance(str_1, str_2):
          """
          The Levenshtein distance is a string metric for measuring the difference
          between two sequences.
          It is calculated as the minimum number of single-character edits necessary to
          transform one string into another.
          """
          ...





          share|improve this answer











          $endgroup$








          • 10




            $begingroup$
            Just to note the module is licensed under GPL 2.0 so watch out if you're using it for work.
            $endgroup$
            – lucasgcb
            Apr 8 at 13:08










          • $begingroup$
            Just to point out a small nitpick to other people who may stumble upon this answer, as per help center: "Every answer must make at least one insightful observation about the code in the question. Answers that merely provide an alternate solution with no explanation or justification do not constitute valid Code Review answers and may be deleted." While this answer does provide alternative and existing module suggestion, it also goes into some suggestions about improving code quality. So it's an example of a decent answer
            $endgroup$
            – Sergiy Kolodyazhnyy
            Apr 9 at 0:02










          • $begingroup$
            Thanks! I did not know of this module. Will check it out
            $endgroup$
            – Kyra_W
            Apr 9 at 8:21






          • 1




            $begingroup$
            @SergiyKolodyazhnyy While I (obviously) agree, and that is one of the reasons I added that part, I would actually argue that "It is implemented in C, so is probably faster than anything you can come up with yourself" would get around the "no explanation or justification" clause
            $endgroup$
            – Graipher
            Apr 9 at 8:21
















          14












          $begingroup$

          There is a module available for exactly that calculation, python-Levenshtein. You can install it with pip install python-Levenshtein.



          It is implemented in C, so is probably faster than anything you can come up with yourself.



          from Levenshtein import distance as levenshtein_distance



          According to the docstring conventions, your docstring should look like this, i.e. with the indentation aligned to the """ and the line length curtailed to 80 characters.



          def calculate_levenshtein_distance(str_1, str_2):
          """
          The Levenshtein distance is a string metric for measuring the difference
          between two sequences.
          It is calculated as the minimum number of single-character edits necessary to
          transform one string into another.
          """
          ...





          share|improve this answer











          $endgroup$








          • 10




            $begingroup$
            Just to note the module is licensed under GPL 2.0 so watch out if you're using it for work.
            $endgroup$
            – lucasgcb
            Apr 8 at 13:08










          • $begingroup$
            Just to point out a small nitpick to other people who may stumble upon this answer, as per help center: "Every answer must make at least one insightful observation about the code in the question. Answers that merely provide an alternate solution with no explanation or justification do not constitute valid Code Review answers and may be deleted." While this answer does provide alternative and existing module suggestion, it also goes into some suggestions about improving code quality. So it's an example of a decent answer
            $endgroup$
            – Sergiy Kolodyazhnyy
            Apr 9 at 0:02










          • $begingroup$
            Thanks! I did not know of this module. Will check it out
            $endgroup$
            – Kyra_W
            Apr 9 at 8:21






          • 1




            $begingroup$
            @SergiyKolodyazhnyy While I (obviously) agree, and that is one of the reasons I added that part, I would actually argue that "It is implemented in C, so is probably faster than anything you can come up with yourself" would get around the "no explanation or justification" clause
            $endgroup$
            – Graipher
            Apr 9 at 8:21














          14












          14








          14





          $begingroup$

          There is a module available for exactly that calculation, python-Levenshtein. You can install it with pip install python-Levenshtein.



          It is implemented in C, so is probably faster than anything you can come up with yourself.



          from Levenshtein import distance as levenshtein_distance



          According to the docstring conventions, your docstring should look like this, i.e. with the indentation aligned to the """ and the line length curtailed to 80 characters.



          def calculate_levenshtein_distance(str_1, str_2):
          """
          The Levenshtein distance is a string metric for measuring the difference
          between two sequences.
          It is calculated as the minimum number of single-character edits necessary to
          transform one string into another.
          """
          ...





          share|improve this answer











          $endgroup$



          There is a module available for exactly that calculation, python-Levenshtein. You can install it with pip install python-Levenshtein.



          It is implemented in C, so is probably faster than anything you can come up with yourself.



          from Levenshtein import distance as levenshtein_distance



          According to the docstring conventions, your docstring should look like this, i.e. with the indentation aligned to the """ and the line length curtailed to 80 characters.



          def calculate_levenshtein_distance(str_1, str_2):
          """
          The Levenshtein distance is a string metric for measuring the difference
          between two sequences.
          It is calculated as the minimum number of single-character edits necessary to
          transform one string into another.
          """
          ...






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Apr 8 at 10:43

























          answered Apr 8 at 10:37









          GraipherGraipher

          27.1k54497




          27.1k54497







          • 10




            $begingroup$
            Just to note the module is licensed under GPL 2.0 so watch out if you're using it for work.
            $endgroup$
            – lucasgcb
            Apr 8 at 13:08










          • $begingroup$
            Just to point out a small nitpick to other people who may stumble upon this answer, as per help center: "Every answer must make at least one insightful observation about the code in the question. Answers that merely provide an alternate solution with no explanation or justification do not constitute valid Code Review answers and may be deleted." While this answer does provide alternative and existing module suggestion, it also goes into some suggestions about improving code quality. So it's an example of a decent answer
            $endgroup$
            – Sergiy Kolodyazhnyy
            Apr 9 at 0:02










          • $begingroup$
            Thanks! I did not know of this module. Will check it out
            $endgroup$
            – Kyra_W
            Apr 9 at 8:21






          • 1




            $begingroup$
            @SergiyKolodyazhnyy While I (obviously) agree, and that is one of the reasons I added that part, I would actually argue that "It is implemented in C, so is probably faster than anything you can come up with yourself" would get around the "no explanation or justification" clause
            $endgroup$
            – Graipher
            Apr 9 at 8:21













          • 10




            $begingroup$
            Just to note the module is licensed under GPL 2.0 so watch out if you're using it for work.
            $endgroup$
            – lucasgcb
            Apr 8 at 13:08










          • $begingroup$
            Just to point out a small nitpick to other people who may stumble upon this answer, as per help center: "Every answer must make at least one insightful observation about the code in the question. Answers that merely provide an alternate solution with no explanation or justification do not constitute valid Code Review answers and may be deleted." While this answer does provide alternative and existing module suggestion, it also goes into some suggestions about improving code quality. So it's an example of a decent answer
            $endgroup$
            – Sergiy Kolodyazhnyy
            Apr 9 at 0:02










          • $begingroup$
            Thanks! I did not know of this module. Will check it out
            $endgroup$
            – Kyra_W
            Apr 9 at 8:21






          • 1




            $begingroup$
            @SergiyKolodyazhnyy While I (obviously) agree, and that is one of the reasons I added that part, I would actually argue that "It is implemented in C, so is probably faster than anything you can come up with yourself" would get around the "no explanation or justification" clause
            $endgroup$
            – Graipher
            Apr 9 at 8:21








          10




          10




          $begingroup$
          Just to note the module is licensed under GPL 2.0 so watch out if you're using it for work.
          $endgroup$
          – lucasgcb
          Apr 8 at 13:08




          $begingroup$
          Just to note the module is licensed under GPL 2.0 so watch out if you're using it for work.
          $endgroup$
          – lucasgcb
          Apr 8 at 13:08












          $begingroup$
          Just to point out a small nitpick to other people who may stumble upon this answer, as per help center: "Every answer must make at least one insightful observation about the code in the question. Answers that merely provide an alternate solution with no explanation or justification do not constitute valid Code Review answers and may be deleted." While this answer does provide alternative and existing module suggestion, it also goes into some suggestions about improving code quality. So it's an example of a decent answer
          $endgroup$
          – Sergiy Kolodyazhnyy
          Apr 9 at 0:02




          $begingroup$
          Just to point out a small nitpick to other people who may stumble upon this answer, as per help center: "Every answer must make at least one insightful observation about the code in the question. Answers that merely provide an alternate solution with no explanation or justification do not constitute valid Code Review answers and may be deleted." While this answer does provide alternative and existing module suggestion, it also goes into some suggestions about improving code quality. So it's an example of a decent answer
          $endgroup$
          – Sergiy Kolodyazhnyy
          Apr 9 at 0:02












          $begingroup$
          Thanks! I did not know of this module. Will check it out
          $endgroup$
          – Kyra_W
          Apr 9 at 8:21




          $begingroup$
          Thanks! I did not know of this module. Will check it out
          $endgroup$
          – Kyra_W
          Apr 9 at 8:21




          1




          1




          $begingroup$
          @SergiyKolodyazhnyy While I (obviously) agree, and that is one of the reasons I added that part, I would actually argue that "It is implemented in C, so is probably faster than anything you can come up with yourself" would get around the "no explanation or justification" clause
          $endgroup$
          – Graipher
          Apr 9 at 8:21





          $begingroup$
          @SergiyKolodyazhnyy While I (obviously) agree, and that is one of the reasons I added that part, I would actually argue that "It is implemented in C, so is probably faster than anything you can come up with yourself" would get around the "no explanation or justification" clause
          $endgroup$
          – Graipher
          Apr 9 at 8:21














          9












          $begingroup$

          The code itself is rather clear. There are some smaller changes I would make



          tuple unpacking



          You can use tuple unpacking to do:



          for code, *_ in ndiff(str1, str2):


          instead of:



          for x in ndiff(str_1, str_2):
          code = x[0]


          dict results:



          Instead of a counter for the additions and removals, I would keep it in 1 dict: counter = ("+": 0, "-": 0)



          def levenshtein_distance(str1, str2, ):
          counter = "+": 0, "-": 0
          distance = 0
          for edit_code, *_ in ndiff(str1, str2):
          if edit_code == " ":
          distance += max(counter.values())
          counter = "+": 0, "-": 0
          else:
          counter[edit_code] += 1
          distance += max(counter.values())
          return distance


          generators



          A smaller, less useful variation, is to let this method be a generator, and use the builtin sum to do the summary. this saves 1 variable inside the function:



          def levenshtein_distance_gen(str1, str2, ):
          counter = "+": 0, "-": 0
          for edit_code, *_ in ndiff(str1, str2):
          if edit_code == " ":
          yield max(counter.values())
          counter = "+": 0, "-": 0
          else:
          counter[edit_code] += 1
          yield max(counter.values())

          sum(levenshtein_distance_gen(str1, str2))



          timings



          The differences in timings between the original and both these variations are minimal, and within the variation of results. This is rather logical, since for simple strings (aaabbbc and abcabcabc) 90% of the time is spent in ndiff






          share|improve this answer









          $endgroup$












          • $begingroup$
            Awesome suggestions. I had not even considered the generator approach, but it looks very nice. Thanks
            $endgroup$
            – Kyra_W
            Apr 9 at 8:24















          9












          $begingroup$

          The code itself is rather clear. There are some smaller changes I would make



          tuple unpacking



          You can use tuple unpacking to do:



          for code, *_ in ndiff(str1, str2):


          instead of:



          for x in ndiff(str_1, str_2):
          code = x[0]


          dict results:



          Instead of a counter for the additions and removals, I would keep it in 1 dict: counter = ("+": 0, "-": 0)



          def levenshtein_distance(str1, str2, ):
          counter = "+": 0, "-": 0
          distance = 0
          for edit_code, *_ in ndiff(str1, str2):
          if edit_code == " ":
          distance += max(counter.values())
          counter = "+": 0, "-": 0
          else:
          counter[edit_code] += 1
          distance += max(counter.values())
          return distance


          generators



          A smaller, less useful variation, is to let this method be a generator, and use the builtin sum to do the summary. this saves 1 variable inside the function:



          def levenshtein_distance_gen(str1, str2, ):
          counter = "+": 0, "-": 0
          for edit_code, *_ in ndiff(str1, str2):
          if edit_code == " ":
          yield max(counter.values())
          counter = "+": 0, "-": 0
          else:
          counter[edit_code] += 1
          yield max(counter.values())

          sum(levenshtein_distance_gen(str1, str2))



          timings



          The differences in timings between the original and both these variations are minimal, and within the variation of results. This is rather logical, since for simple strings (aaabbbc and abcabcabc) 90% of the time is spent in ndiff






          share|improve this answer









          $endgroup$












          • $begingroup$
            Awesome suggestions. I had not even considered the generator approach, but it looks very nice. Thanks
            $endgroup$
            – Kyra_W
            Apr 9 at 8:24













          9












          9








          9





          $begingroup$

          The code itself is rather clear. There are some smaller changes I would make



          tuple unpacking



          You can use tuple unpacking to do:



          for code, *_ in ndiff(str1, str2):


          instead of:



          for x in ndiff(str_1, str_2):
          code = x[0]


          dict results:



          Instead of a counter for the additions and removals, I would keep it in 1 dict: counter = ("+": 0, "-": 0)



          def levenshtein_distance(str1, str2, ):
          counter = "+": 0, "-": 0
          distance = 0
          for edit_code, *_ in ndiff(str1, str2):
          if edit_code == " ":
          distance += max(counter.values())
          counter = "+": 0, "-": 0
          else:
          counter[edit_code] += 1
          distance += max(counter.values())
          return distance


          generators



          A smaller, less useful variation, is to let this method be a generator, and use the builtin sum to do the summary. this saves 1 variable inside the function:



          def levenshtein_distance_gen(str1, str2, ):
          counter = "+": 0, "-": 0
          for edit_code, *_ in ndiff(str1, str2):
          if edit_code == " ":
          yield max(counter.values())
          counter = "+": 0, "-": 0
          else:
          counter[edit_code] += 1
          yield max(counter.values())

          sum(levenshtein_distance_gen(str1, str2))



          timings



          The differences in timings between the original and both these variations are minimal, and within the variation of results. This is rather logical, since for simple strings (aaabbbc and abcabcabc) 90% of the time is spent in ndiff






          share|improve this answer









          $endgroup$



          The code itself is rather clear. There are some smaller changes I would make



          tuple unpacking



          You can use tuple unpacking to do:



          for code, *_ in ndiff(str1, str2):


          instead of:



          for x in ndiff(str_1, str_2):
          code = x[0]


          dict results:



          Instead of a counter for the additions and removals, I would keep it in 1 dict: counter = ("+": 0, "-": 0)



          def levenshtein_distance(str1, str2, ):
          counter = "+": 0, "-": 0
          distance = 0
          for edit_code, *_ in ndiff(str1, str2):
          if edit_code == " ":
          distance += max(counter.values())
          counter = "+": 0, "-": 0
          else:
          counter[edit_code] += 1
          distance += max(counter.values())
          return distance


          generators



          A smaller, less useful variation, is to let this method be a generator, and use the builtin sum to do the summary. this saves 1 variable inside the function:



          def levenshtein_distance_gen(str1, str2, ):
          counter = "+": 0, "-": 0
          for edit_code, *_ in ndiff(str1, str2):
          if edit_code == " ":
          yield max(counter.values())
          counter = "+": 0, "-": 0
          else:
          counter[edit_code] += 1
          yield max(counter.values())

          sum(levenshtein_distance_gen(str1, str2))



          timings



          The differences in timings between the original and both these variations are minimal, and within the variation of results. This is rather logical, since for simple strings (aaabbbc and abcabcabc) 90% of the time is spent in ndiff







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Apr 8 at 13:51









          Maarten FabréMaarten Fabré

          5,234517




          5,234517











          • $begingroup$
            Awesome suggestions. I had not even considered the generator approach, but it looks very nice. Thanks
            $endgroup$
            – Kyra_W
            Apr 9 at 8:24
















          • $begingroup$
            Awesome suggestions. I had not even considered the generator approach, but it looks very nice. Thanks
            $endgroup$
            – Kyra_W
            Apr 9 at 8:24















          $begingroup$
          Awesome suggestions. I had not even considered the generator approach, but it looks very nice. Thanks
          $endgroup$
          – Kyra_W
          Apr 9 at 8:24




          $begingroup$
          Awesome suggestions. I had not even considered the generator approach, but it looks very nice. Thanks
          $endgroup$
          – Kyra_W
          Apr 9 at 8:24










          Kyra_W is a new contributor. Be nice, and check out our Code of Conduct.









          draft saved

          draft discarded


















          Kyra_W is a new contributor. Be nice, and check out our Code of Conduct.












          Kyra_W is a new contributor. Be nice, and check out our Code of Conduct.











          Kyra_W is a new contributor. Be nice, and check out our Code of Conduct.














          Thanks for contributing an answer to Code Review Stack Exchange!


          • 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.

          Use MathJax to format equations. MathJax reference.


          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%2fcodereview.stackexchange.com%2fquestions%2f217065%2fcalculate-levenshtein-distance-between-two-strings-in-python%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

          Club Baloncesto Breogán Índice Historia | Pavillón | Nome | O Breogán na cultura popular | Xogadores | Adestradores | Presidentes | Palmarés | Historial | Líderes | Notas | Véxase tamén | Menú de navegacióncbbreogan.galCadroGuía oficial da ACB 2009-10, páxina 201Guía oficial ACB 1992, páxina 183. Editorial DB.É de 6.500 espectadores sentados axeitándose á última normativa"Estudiantes Junior, entre as mellores canteiras"o orixinalHemeroteca El Mundo Deportivo, 16 setembro de 1970, páxina 12Historia do BreogánAlfredo Pérez, o último canoneiroHistoria C.B. BreogánHemeroteca de El Mundo DeportivoJimmy Wright, norteamericano do Breogán deixará Lugo por ameazas de morteResultados de Breogán en 1986-87Resultados de Breogán en 1990-91Ficha de Velimir Perasović en acb.comResultados de Breogán en 1994-95Breogán arrasa al Barça. "El Mundo Deportivo", 27 de setembro de 1999, páxina 58CB Breogán - FC BarcelonaA FEB invita a participar nunha nova Liga EuropeaCharlie Bell na prensa estatalMáximos anotadores 2005Tempada 2005-06 : Tódolos Xogadores da Xornada""Non quero pensar nunha man negra, mais pregúntome que está a pasar""o orixinalRaúl López, orgulloso dos xogadores, presume da boa saúde económica do BreogánJulio González confirma que cesa como presidente del BreogánHomenaxe a Lisardo GómezA tempada do rexurdimento celesteEntrevista a Lisardo GómezEl COB dinamita el Pazo para forzar el quinto (69-73)Cafés Candelas, patrocinador del CB Breogán"Suso Lázare, novo presidente do Breogán"o orixinalCafés Candelas Breogán firma el mayor triunfo de la historiaEl Breogán realizará 17 homenajes por su cincuenta aniversario"O Breogán honra ao seu fundador e primeiro presidente"o orixinalMiguel Giao recibiu a homenaxe do PazoHomenaxe aos primeiros gladiadores celestesO home que nos amosa como ver o Breo co corazónTita Franco será homenaxeada polos #50anosdeBreoJulio Vila recibirá unha homenaxe in memoriam polos #50anosdeBreo"O Breogán homenaxeará aos seus aboados máis veteráns"Pechada ovación a «Capi» Sanmartín e Ricardo «Corazón de González»Homenaxe por décadas de informaciónPaco García volve ao Pazo con motivo do 50 aniversario"Resultados y clasificaciones""O Cafés Candelas Breogán, campión da Copa Princesa""O Cafés Candelas Breogán, equipo ACB"C.B. Breogán"Proxecto social"o orixinal"Centros asociados"o orixinalFicha en imdb.comMario Camus trata la recuperación del amor en 'La vieja música', su última película"Páxina web oficial""Club Baloncesto Breogán""C. B. Breogán S.A.D."eehttp://www.fegaba.com

          Vilaño, A Laracha Índice Patrimonio | Lugares e parroquias | Véxase tamén | Menú de navegación43°14′52″N 8°36′03″O / 43.24775, -8.60070

          Cegueira Índice Epidemioloxía | Deficiencia visual | Tipos de cegueira | Principais causas de cegueira | Tratamento | Técnicas de adaptación e axudas | Vida dos cegos | Primeiros auxilios | Crenzas respecto das persoas cegas | Crenzas das persoas cegas | O neno deficiente visual | Aspectos psicolóxicos da cegueira | Notas | Véxase tamén | Menú de navegación54.054.154.436928256blindnessDicionario da Real Academia GalegaPortal das Palabras"International Standards: Visual Standards — Aspects and Ranges of Vision Loss with Emphasis on Population Surveys.""Visual impairment and blindness""Presentan un plan para previr a cegueira"o orixinalACCDV Associació Catalana de Cecs i Disminuïts Visuals - PMFTrachoma"Effect of gene therapy on visual function in Leber's congenital amaurosis"1844137110.1056/NEJMoa0802268Cans guía - os mellores amigos dos cegosArquivadoEscola de cans guía para cegos en Mortágua, PortugalArquivado"Tecnología para ciegos y deficientes visuales. Recopilación de recursos gratuitos en la Red""Colorino""‘COL.diesis’, escuchar los sonidos del color""COL.diesis: Transforming Colour into Melody and Implementing the Result in a Colour Sensor Device"o orixinal"Sistema de desarrollo de sinestesia color-sonido para invidentes utilizando un protocolo de audio""Enseñanza táctil - geometría y color. Juegos didácticos para niños ciegos y videntes""Sistema Constanz"L'ocupació laboral dels cecs a l'Estat espanyol està pràcticament equiparada a la de les persones amb visió, entrevista amb Pedro ZuritaONCE (Organización Nacional de Cegos de España)Prevención da cegueiraDescrición de deficiencias visuais (Disc@pnet)Braillín, un boneco atractivo para calquera neno, con ou sen discapacidade, que permite familiarizarse co sistema de escritura e lectura brailleAxudas Técnicas36838ID00897494007150-90057129528256DOID:1432HP:0000618D001766C10.597.751.941.162C97109C0155020