How to Consolidate if statements in Python for Text replacement

Question:

I have the following code I wrote in python, but I want to make it easier to maintain.

from tkinter import *
from tkinter import filedialog
import os
from docx import document


def replace_text(file_path, b1o, b1a, b1p, b1e):
  document = document(file_path)
   for paragraph in document.paragraphs:
    if 'B1O' in paragraph.text:
        paragraph.text = paragraph.text.replace('B1O', b1o)
    if 'B1A' in paragraph.text:
        paragraph.text = paragraph.text.replace('B1A', b1a)
    if 'B1P' in paragraph.text:
        paragraph.text = paragraph.text.replace('B1P', b1p)
    if 'B1E' in paragraph.text:
        paragraph.text = paragraph.text.replace('B1E', b1e)
return document

How can I combine the if statements and make them easier to manage?

I’ve looked at How to consolidate if / elif statements in Python, but I’m unsure how to utilize the solution with this particular use case.

Thanks for any input!

EDIT: Here is the rest of the program snipped to include only the parts mentioned here.

def generate_file():
    # Open a file dialog to select a template file
    root = Tk()
    root.withdraw()
    file_path = filedialog.askopenfilename(
        title="Select a template file",
        filetypes=[("Word files", "*.docx")],
        initialdir=r"C://desktop/Templates"
    )

# Get user input for variables
    b1o = input("Enter the name of the owner: ")
    b1a = input("Enter the address: ")
    b1p = input("Enter the phone number: ")
    b1e = input("Enter the email address: ")

# Replace placeholders with user input
    document = replace_text(file_path, b1o, b1a, b1p, b1e)

# Open a file dialog to select a folder to save the new file
    folder_path = filedialog.askdirectory(title="Select a folder to save the new file")
    file_name = os.path.splitext(os.path.basename(file_path))[0] + "_" + b1p + "_" + b1o + ".docx"
    file_path = os.path.join(folder_path, file_name)

# Save the modified document as a new file
    document.save(file_path)
    print("File saved at:", file_path)

    root = Tk()
    root.title("Generate New Document")

# Create a button to generate a new file
    generate_button = Button(root, text="Select Template and 
    Generate", command=generate_file)
    generate_button.pack()

root.mainloop()
Asked By: Devon

||

Answers:

An efficient fix might look something like:

import re
import functools

def replace_text(file_path, b1o, b1a, b1p, b1e):
    document = document(file_path)
    replacements = { 'B1O': b1o, 'B1A': b1a, 'B1P': b1p, 'B1E': b1e }
    subFn = functools.partial(
      re.sub,
      '|'.join(re.escape(k) for k in replacements.keys()),
      lambda match: replacements[match.group(0)]
    )
    for paragraph in document.paragraphs:
        paragraph.text = subFn(paragraph.text)
    return document

Using re.sub() lets us search for all four strings in a single pass, instead of needing to search for them one after the other.

Answered By: Charles Duffy

How about building a find and replace dictionary that you can maintain.

def replace_text(file_path, b1o, b1a, b1p, b1e):
    find_replace = {'B1O': b1o, 'B1A': b1a, 'B1P': b1p, 'B1E': b1e}
    document = document(file_path)
    for paragraph in document.paragraphs:
        for to_find, to_replace in find_replace.items():
            paragraph.text = paragraph.text.replace(to_find, to_replace)
    return document
Answered By: JonSG

You dont need if statements. If the text is not there, nothing will be replaced, easy as this 🙂

def replace_text(file_path, b1o, b1a, b1p, b1e):
    document = document(file_path)

    for paragraph in document.paragraphs:
        for source, target in zip(
            ["B10", "B1A", "B1P", "B1E"],
            [b1o, b1a, b1p, b1e]
        ):
            paragraph.text = paragraph.text.replace(source, target)
    return document
Answered By: Klops
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.