Create a compress function in Python?

后端 未结 19 1190
感动是毒
感动是毒 2021-01-05 03:37

I need to create a function called compress that compresses a string by replacing any repeated letters with a letter and number. My function should return the shortened vers

19条回答
  •  慢半拍i
    慢半拍i (楼主)
    2021-01-05 04:33

    For a coding interview, where it was about the algorithm, and not about my knowledge of Python, its internal representation of data structures, or the time complexity of operations such as string concatenation:

    def compress(message: str) -> str:
        output = ""
        length = 0
        previous: str = None
        for char in message:
            if previous is None or char == previous:
                length += 1
            else:
                output += previous
                if length > 1:
                    output += str(length)
                length = 1
            previous = char
        if previous is not None:
            output += previous
            if length > 1:
                output += str(length)
        return output
    

    For code I'd actually use in production, not reinventing any wheels, being more testable, using iterators until the last step for space efficiency, and using join() instead of string concatenation for time efficiency:

    from itertools import groupby
    from typing import Iterator
    
    
    def compressed_groups(message: str) -> Iterator[str]:
        for char, group in groupby(message):
            length = sum(1 for _ in group)
            yield char + (str(length) if length > 1 else "")
    
    
    def compress(message: str) -> str:
        return "".join(compressed_groups(message))
    

    Taking things a step further, for even more testability:

    from itertools import groupby
    from typing import Iterator
    from collections import namedtuple
    
    
    class Segment(namedtuple('Segment', ['char', 'length'])):
    
        def __str__(self) -> str:
            return self.char + (str(self.length) if self.length > 1 else "")
    
    
    def segments(message: str) -> Iterator[Segment]:
        for char, group in groupby(message):
            yield Segment(char, sum(1 for _ in group))
    
    
    def compress(message: str) -> str:
        return "".join(str(s) for s in segments(message))
    

    Going all-out and providing a Value Object CompressedString:

    from itertools import groupby
    from typing import Iterator
    from collections import namedtuple
    
    
    class Segment(namedtuple('Segment', ['char', 'length'])):
    
        def __str__(self) -> str:
            return self.char + (str(self.length) if self.length > 1 else "")
    
    
    class CompressedString(str):
    
        @classmethod
        def compress(cls, message: str) -> "CompressedString":
            return cls("".join(str(s) for s in cls._segments(message)))
    
        @staticmethod
        def _segments(message: str) -> Iterator[Segment]:
            for char, group in groupby(message):
                yield Segment(char, sum(1 for _ in group))
    
    
    def compress(message: str) -> str:
        return CompressedString.compress(message)
    

提交回复
热议问题