Skip to content
Snippets Groups Projects
string_replacements.py 2.66 KiB
Newer Older
Michał Pogoda's avatar
Michał Pogoda committed
from typing import List, Tuple, Any, TypeVar
Michał Pogoda's avatar
Michał Pogoda committed

def replace(original_string: str, replacements: List[Tuple[int, int, str]]) -> str:
    """
    Replaces substrings in a string.
    
Michał Pogoda's avatar
Michał Pogoda committed
    !!! Important: This function assumes that there are no overlapping annotations.

    Parameters
    ----------
    original_string : str
        The original string.
    replacements : List[Tuple[int, int, str]]
        A list of tuples containing (start, end, replacement).
    Returns
    -------
    str
        The string with replacements applied.
    """
    replacements = sorted(replacements, key=lambda x: x[0])
    delta = 0
    for replacement in replacements:
Michał Pogoda's avatar
Michał Pogoda committed
        original_string = (
            original_string[: replacement[0] + delta]
            + replacement[2]
            + original_string[replacement[1] + delta :]
        )
        delta += len(replacement[2]) - (replacement[1] - replacement[0])
Michał Pogoda's avatar
Michał Pogoda committed

    return original_string


_T = TypeVar("_T")


def replace_and_update(
    original_string: str,
    replacements: List[Tuple[int, int, str]],
    other_annotations: List[Tuple[int, int, _T]],
) -> Tuple[str, List[Tuple[int, int, _T]]]:
    """ Replaces substrings in a string and updates other annotations to match new string.
    
    !!! Important: This function assumes that there are no overlapping annotations.

    Parameters
    ----------
    original_string : str
        The original string.
    replacements : List[Tuple[int, int, str]]
        A list of tuples containing (start, end, replacement).
    other_annotations : List[Tuple[int, int, Any]]
        A list of other annotations.

    Returns
    -------
    Tuple[str, List[Tuple[int, int, Any]]]
        The string with replacements applied and other annotations with new positions.
    """
    
    joined_list = []
    for replacement in replacements:
        joined_list.append((replacement[0], replacement[1], replacement[2], True))
    for other_annotation in other_annotations:
        joined_list.append((other_annotation[0], other_annotation[1], other_annotation[2], False))

    annotations = sorted(joined_list, key=lambda x: x[0])
    
    new_other_annotations = []

    delta = 0
    for annotation in annotations:
        is_replacement = annotation[3]
Michał Pogoda's avatar
Michał Pogoda committed
        if is_replacement:
            original_string = (
                original_string[: annotation[0] + delta]
                + annotation[2]
                + original_string[annotation[1] + delta :]
            )
            delta += len(annotation[2]) - (annotation[1] - annotation[0])
        else:
            new_other_annotations.append((annotation[0] + delta, annotation[1] + delta, annotation[2]))

    return original_string, new_other_annotations