Splitting, Joining and Processing Text

split turns text into a list, join turns a list back into text, and between those two calls sits most of the text processing you will ever write.

split

sentence = "the quick brown fox"

print(sentence.split())              # ['the', 'quick', 'brown', 'fox']
print(sentence.split("o"))           # ['the quick br', 'wn f', 'x']

csv_line = "Meera,27,Pune"
print(csv_line.split(","))           # ['Meera', '27', 'Pune']

print("a,b,c".split(",", 1))         # ['a', 'b,c'] - at most one split
print("a,b,c".rsplit(",", 1))        # ['a,b', 'c'] - splitting from the right

split() with no argument is special

messy = "  the   quick \t brown \n fox  "

print(messy.split())          # ['the', 'quick', 'brown', 'fox'] - clean
print(messy.split(" "))       # lots of empty strings between the words

With no argument, split treats any run of whitespace as one separator and ignores leading and trailing whitespace. With an explicit separator it splits on every single occurrence, producing empty strings between consecutive separators. The no argument form is almost always what you want for words.

splitlines

document = "first line\nsecond line\r\nthird line"

print(document.splitlines())          # three items, both newline styles handled
print(document.split("\n"))           # leaves a stray \r on the second item

partition

setting = "timeout=30"

key, separator, value = setting.partition("=")
print(key, value)                  # timeout 30

# It always returns three items, even when the separator is missing.
print("nokey".partition("="))      # ('nokey', '', '')

partition is the right tool when a line has exactly one separator and the value itself may contain more, for example a URL or a message with a colon.

join

words = ["the", "quick", "brown", "fox"]

print(" ".join(words))          # the quick brown fox
print("-".join(words))          # the-quick-brown-fox
print("".join(words))           # thequickbrownfox
print("\n".join(words))         # one per line

print(", ".join(["a"]))         # a - no trailing separator
print(", ".join([]))            # empty string, no error
The separator is the string you call the method on, and the argument is the sequence. It reads backwards the first time. Remember it as "glue dot join list".

join needs strings

numbers = [1, 2, 3]
# print(", ".join(numbers))            # TypeError: expected str instance
print(", ".join(str(n) for n in numbers))   # 1, 2, 3
print(", ".join(map(str, numbers)))         # 1, 2, 3

The round trip

line = "Meera, 27 , Pune"

fields = [field.strip() for field in line.split(",")]
print(fields)                       # ['Meera', '27', 'Pune']
print("|".join(fields))             # Meera|27|Pune

Split, clean each part, rejoin. That three step shape covers a large share of real text processing.

Worked examples

Parsing a simple configuration file

config_text = """
# connection settings
host = localhost
port = 8080

timeout = 30
"""

settings = {}
for line in config_text.splitlines():
    line = line.strip()
    if not line or line.startswith("#"):
        continue
    key, separator, value = line.partition("=")
    if separator:
        settings[key.strip()] = value.strip()

print(settings)     # {'host': 'localhost', 'port': '8080', 'timeout': '30'}

Counting words

text = "The cat sat. The cat slept! A cat."

words = [w.strip(".,!?").lower() for w in text.split()]
counts = {}
for word in words:
    counts[word] = counts.get(word, 0) + 1

for word, count in sorted(counts.items(), key=lambda pair: -pair[1]):
    print(word, count)

Reversing the words of a sentence

sentence = "python makes text processing easy"
print(" ".join(reversed(sentence.split())))
# easy processing text makes python

Turning a title into a URL slug

def slugify(title):
    cleaned = "".join(ch if ch.isalnum() or ch.isspace() else " " for ch in title)
    return "-".join(cleaned.lower().split())


print(slugify("Python: Strings & Text Processing!"))
# python-strings-text-processing

Handling CSV like data, and its limits

rows = [
    "name,age,city",
    "Meera,27,Pune",
    "Arun,31,Kochi",
]

header = rows[0].split(",")
for row in rows[1:]:
    values = row.split(",")
    record = dict(zip(header, values))
    print(record)

This works for simple, well behaved data. It breaks the moment a field contains a comma inside quotes. Real CSV has a standard module in the library, covered in the standard library notes; splitting by hand is for data you control.

Common mistakes

  • Calling split(" ") on text with irregular spacing.
  • Getting the join argument order backwards.
  • Passing non strings to join.
  • Using split("\n") on text that may contain Windows line endings.
  • Parsing CSV by splitting on commas when fields may be quoted.
  • Forgetting to strip() each field after splitting.

Best practices

  • Use bare split() for words, splitlines() for lines, partition() for key and value pairs.
  • Always strip fields after splitting user supplied or file supplied data.
  • Use join rather than accumulating with +=.
  • Use maxsplit when only the first or last separator matters.

Practice

  1. Explain the difference between "a b".split() and "a b".split(" ").
  2. Parse "2026-08-22" into three integers using one call to split.
  3. Write a function that takes a sentence and returns it with each word reversed but the word order unchanged.
  4. Parse the config example above and handle a line that has no = sign without crashing.
  5. Explain why partition is safer than split("=") for a line such as url = http://a.com/b=c.

Conclusion

split and join are inverses, and almost all text processing is split, transform the pieces, join. Learn the no argument split, splitlines and partition, and reach for the standard library the moment your data format has quoting rules of its own.

Written by Lorens Mishra

Default administrator account created by the installer.

Continue reading

All Python notes →

Discussion

0 comments
Sign in to join the discussion.

No comments yet. Be the first to say something.