Comparing Strings using Python

In Python, strings are sequences of characters, which are effectively stored in memory as an object. Each object can be identified using the id() method, as you can see below. Python tries to re-use objects in memory that have the same value, which also makes comparing objects very fast in Python:

$ python
Python 3.9.0 (v3.9.0:9cf6752276, Oct  5 2020, 11:29:23) 
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = "abc"
>>> b = "abc"
>>> c = "def"
>>> print (id(a), id(b), id(c))
(139949123041320, 139949123041320, 139949122390576)
>>> quit()

In order to compare strings, Python offers a few different operators to do so. First, we will explain them in more detail below. Second, we’ll go over both the string and the re modules, which contain methods to handle case-insensitive and inexact matches. Third, to deal with multi-line strings the difflib module is quite handy. A number of examples will help you to understand how to use them.

Compare Strngs with the The == and != Operators

As a basic comparison operator you’ll want to use == and !=. They work in exactly the same way as with integer and float values. The == operator returns True if there is an exact match, otherwise False will be returned. In contrast, the != operator returns True if there is no match and otherwise returns False. Listing 1 demonstrates this.

In a for loop, a string containing the name of the Swiss city “Lausanne” is compared with an entry from a list of other places, and the comparison result is printed on stdout.

Listing 1:


listOfPlaces = ["Berlin", "Paris", "Lausanne"]
currentCity = "Lausanne"

for place in listOfPlaces:
    print (f"comparing {place} with {currentCity}: %{place == currentCity}")

Running the Python script from above the output is as follows:

$ python3 comparing-strings.py
comparing Berlin with Lausanne: False
comparing Paris with Lausanne: False
comparing Lausanne with Lausanne: True

The == and is Operators

Python has the two comparison operators == and is. At first sight they seem to be the same, but actually they are not.

== compares two variables based on the value they represent. In contrast, the is operator compares two variables based on the object ID in memory.

John (Doe) and John (Moe) are both called John. If we can reduce them to just their names, they’d be equal in value, but still two different people qualitatively.

The next example demonstrates that for three variables with string values. The two variables a and b have the same value, and Python refers to the same object in order to minimize memory usage.

This is done for simple types and strings by default, but not for other objects:

>>> a = 'hello'
>>> b = 'hello'
>>> c = 'world'
>>> a is b
True
>>> a is c
False
>>> id(a)
140666888153840
>>> id(b)
140666888153840
>>> 

As soon as the value changes Python will reinstantiate the object and assign the variable. In the next code snippet b gets the value of 2, and subsequently b and c refer to the same object:

>>> b = 'world'
>>> id(b)
140666888154416
>>> id(c)
140666888154416

More Comparison Operators

For a comparison regarding a lexicographical order you can use the comparison operators <, >, <=, and >=. The comparison itself is done character by character. The order depends on the order of the characters in the alphabet. This order depends on the character table that is in use on your machine while executing the Python code.

Keep in mind the order is case-sensitive. As an example for the Latin alphabet, “Bus” comes before “bus”. Listing 2 shows how these comparison operators work in practice.

Listing 2:


listOfPlaces = ["Berlin", "Paris", "Lausanne"]
currentCity = "Lausanne"

for place in listOfPlaces:
    if place < currentCity:
            print (f"{place} comes before {currentCity}")
    elif place > currentCity:
            print (f"{place} comes after {currentCity}")
    else:
            print (f"{place} is equal to {currentCity}")

Running the Python script from above the output is as follows:

$ python3 comparing-strings-order.py
Berlin comes before Lausanne
Paris comes after Lausanne
Lausanne is equal to Lausanne

Case-Insensitive String Comparisons

The previous examples focused on exact matches between strings. To allow case-insensitive comparisons Python offers special string methods such as upper() and lower(). Both of them are directly available as methods of the according string object.

upper() converts the entire string into uppercase letters, and lower() into lowercase letters, respectively. Based on Listing 1 the next listing shows how to use the lower() method.

Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!

Listing 3:


listOfPlaces = ["Berlin", "Paris", "Lausanne"]
currentCity = "lausANne"

for place in listOfPlaces:
    print (f"comparing {place} with {place.lower() == currentCity.lower()}: {currentCity}")

The output is as follows:

$ python3 comparing-strings-case-insensitive.py
comparing Berlin with lausANne: False
comparing Paris with lausANne: False
comparing Lausanne with lausANne: True

Compare Strings Using Regular Expressions (RegEx)

A Regular Expression – or “regex” for short – defines a specific pattern of characters.

To make use of this mechanism in Python import the re module first and define a specific pattern, next. Again, the following example is based on Listing 1. The search pattern matches “bay”, and begins with either a lowercase or an uppercase letter. Precisely, the following Python code finds all the strings in which the search pattern occurs no matter at which position of the string – at the beginning, or in the middle, or at the end.

Listing 4:


import re


listOfPlaces = ["Bayswater", "Table Bay", "Bejing", "Bombay"]


pattern = re.compile("[Bb]ay")

for place in listOfPlaces:
    if pattern.search(place):
        print (f"{place} matches the search pattern")

The output is as follows, and matches “Bayswater”, “Table Bay”, and “Bombay” from the list of places:

$ python3 comparing-strings-re.py
Bayswater matches the search pattern
Table Bay matches the search pattern
Bombay matches the search pattern

Multi-Line and List Comparisons

So far our comparisons have only been on a few words. Using the difflib module Python also offers a way to compare multi-line strings, and entire lists of words. The output can be configured according to various formats of diff tools.

The next example (Listing 5) compares two multi-line strings line by line, and shows deletions as well as additions. After the initialization of the Differ object in line 12 the comparison is made using the compare() method in line 15. The result is printed on the standard output:


import difflib
 


original = ["About the IIS", "", "IIS 8.5 has several improvements related", "to performance in large-scale scenarios, such", "as those used by commercial hosting providers and Microsoft's", "own cloud offerings."]


edited = ["About the IIS", "", "It has several improvements related", "to performance in large-scale scenarios."]


d = difflib.Differ()
 

diff = d.compare(original, edited)
 

print ('n'.join(diff))

Running the script creates the output as seen below. Lines with deletions are indicated by - signs whereas lines with additions start with a + sign. Furthermore, lines with changes start with a question mark. Changes are indicated using ^ signs at the according position. Lines without an indicator are still the same:

$ python comparing-strings-difflib.py
  About the IIS
  
- IIS 8.5 has several improvements related
?  ^^^^^^

+ It has several improvements related
?  ^

- to performance in large-scale scenarios, such
?                                        ^^^^^^

+ to performance in large-scale scenarios.
?                                        ^

- as those used by commercial hosting providers and Microsoft's
- own cloud offerings.

Conclusion

In this article you have learned various ways to compare strings in Python. We hope that this overview helps you effectively programming in your developer’s life.

Acknowledgements

The author would like to thank Mandy Neumeyer for her support while preparing the article.

Time Stamp:

More from Stackabuse