在Python中如何将字符串截断为75个字符?

在JavaScript中是这样做的:

var data="saddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsaddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsadddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
var info = (data.length > 75) ? data.substring[0,75] + '..' : data;

当前回答

下面是一个简单的函数,它将从任意一侧截断给定字符串:

def truncate(string, length=75, beginning=True, insert='..'):
    '''Shorten the given string to the given length.
    An ellipsis will be added to the section trimmed.

    :Parameters:
        length (int) = The maximum allowed length before trunicating.
        beginning (bool) = Trim starting chars, else; ending.
        insert (str) = Chars to add at the trimmed area. (default: ellipsis)

    :Return:
        (str)

    ex. call: truncate('12345678', 4)
        returns: '..5678'
    '''
    if len(string)>length:
        if beginning: #trim starting chars.
            string = insert+string[-length:]
        else: #trim ending chars.
            string = string[:length]+insert
    return string

其他回答

假设string是我们希望截断的字符串,而nchars是输出字符串中所需的字符数。

stryng = "sadddddddddddddddddddddddddddddddddddddddddddddddddd"
nchars = 10

我们可以像下面这样截断字符串:

def truncate(stryng:str, nchars:int):
    return (stryng[:nchars - 6] + " [...]")[:min(len(stryng), nchars)]

某些测试用例的结果如下所示:

s = "sadddddddddddddddddddddddddddddd!"
s = "sa" + 30*"d" + "!"

truncate(s, 2)                ==  sa
truncate(s, 4)                ==  sadd
truncate(s, 10)               ==  sadd [...]
truncate(s, len(s)//2)        ==  sadddddddd [...]

我的解决方案为上面的测试用例产生了合理的结果。

但一些病理病例如下:

一些病理病例!

truncate(s, len(s) - 3)()       ==  sadddddddddddddddddddddd [...]
truncate(s, len(s) - 2)()       ==  saddddddddddddddddddddddd [...]
truncate(s, len(s) - 1)()       ==  sadddddddddddddddddddddddd [...]
truncate(s, len(s) + 0)()       ==  saddddddddddddddddddddddddd [...]
truncate(s, len(s) + 1)()       ==  sadddddddddddddddddddddddddd [...
truncate(s, len(s) + 2)()       ==  saddddddddddddddddddddddddddd [..
truncate(s, len(s) + 3)()       ==  sadddddddddddddddddddddddddddd [.
truncate(s, len(s) + 4)()       ==  saddddddddddddddddddddddddddddd [
truncate(s, len(s) + 5)()       ==  sadddddddddddddddddddddddddddddd 
truncate(s, len(s) + 6)()       ==  sadddddddddddddddddddddddddddddd!
truncate(s, len(s) + 7)()       ==  sadddddddddddddddddddddddddddddd!
truncate(s, 9999)()             ==  sadddddddddddddddddddddddddddddd!

值得注意的是,

当字符串包含换行字符(\n)时,可能会出现问题。 当nchars > len(s)时,我们应该打印字符串s,而不是试图打印“[…]”

下面是更多的代码:

import io

class truncate:
    """
        Example of Code Which Uses truncate:
        ```
            s = "\r<class\n 'builtin_function_or_method'>"
            s = truncate(s, 10)()
            print(s)
                    ```
                Examples of Inputs and Outputs:
                        truncate(s, 2)()   ==  \r
                        truncate(s, 4)()   ==  \r<c
                        truncate(s, 10)()  ==  \r<c [...]
                        truncate(s, 20)()  ==  \r<class\n 'bu [...]
                        truncate(s, 999)() ==  \r<class\n 'builtin_function_or_method'>
                    ```
                Other Notes:
                    Returns a modified copy of string input
                    Does not modify the original string
            """
    def __init__(self, x_stryng: str, x_nchars: int) -> str:
        """
        This initializer mostly exists to sanitize function inputs
        """
        try:
            stryng = repr("".join(str(ch) for ch in x_stryng))[1:-1]
            nchars = int(str(x_nchars))
        except BaseException as exc:
            invalid_stryng =  str(x_stryng)
            invalid_stryng_truncated = repr(type(self)(invalid_stryng, 20)())

            invalid_x_nchars = str(x_nchars)
            invalid_x_nchars_truncated = repr(type(self)(invalid_x_nchars, 20)())

            strm = io.StringIO()
            print("Invalid Function Inputs", file=strm)
            print(type(self).__name__, "(",
                  invalid_stryng_truncated,
                  ", ",
                  invalid_x_nchars_truncated, ")", sep="", file=strm)
            msg = strm.getvalue()

            raise ValueError(msg) from None

        self._stryng = stryng
        self._nchars = nchars

    def __call__(self) -> str:
        stryng = self._stryng
        nchars = self._nchars
        return (stryng[:nchars - 6] + " [...]")[:min(len(stryng), nchars)]

下面是一个简单的函数,它将从任意一侧截断给定字符串:

def truncate(string, length=75, beginning=True, insert='..'):
    '''Shorten the given string to the given length.
    An ellipsis will be added to the section trimmed.

    :Parameters:
        length (int) = The maximum allowed length before trunicating.
        beginning (bool) = Trim starting chars, else; ending.
        insert (str) = Chars to add at the trimmed area. (default: ellipsis)

    :Return:
        (str)

    ex. call: truncate('12345678', 4)
        returns: '..5678'
    '''
    if len(string)>length:
        if beginning: #trim starting chars.
            string = insert+string[-length:]
        else: #trim ending chars.
            string = string[:length]+insert
    return string

你不能像动态分配C字符串那样“截断”Python字符串。Python中的字符串是不可变的。您可以像其他答案中描述的那样对字符串进行切片,生成一个只包含由切片偏移量和步长定义的字符的新字符串。 在某些(不实际的)情况下,这可能有点烦人,比如当你选择Python作为面试语言时,面试官要求你从一个字符串中删除重复的字符。哎。

这是一个函数,我把它作为一个新的String类的一部分…它允许添加后缀(如果字符串是修剪后的大小,并且添加它足够长-尽管你不需要强制绝对大小)

我在改变一些东西的过程中,所以有一些无用的逻辑成本(如果_truncate…例如),不再需要它,并且在顶部有一个return…

但是,它仍然是一个截断数据的好函数……

##
## Truncate characters of a string after _len'nth char, if necessary... If _len is less than 0, don't truncate anything... Note: If you attach a suffix, and you enable absolute max length then the suffix length is subtracted from max length... Note: If the suffix length is longer than the output then no suffix is used...
##
## Usage: Where _text = 'Testing', _width = 4
##      _data = String.Truncate( _text, _width )                        == Test
##      _data = String.Truncate( _text, _width, '..', True )            == Te..
##
## Equivalent Alternates: Where _text = 'Testing', _width = 4
##      _data = String.SubStr( _text, 0, _width )                       == Test
##      _data = _text[  : _width ]                                      == Test
##      _data = ( _text )[  : _width ]                                  == Test
##
def Truncate( _text, _max_len = -1, _suffix = False, _absolute_max_len = True ):
    ## Length of the string we are considering for truncation
    _len            = len( _text )

    ## Whether or not we have to truncate
    _truncate       = ( False, True )[ _len > _max_len ]

    ## Note: If we don't need to truncate, there's no point in proceeding...
    if ( not _truncate ):
        return _text

    ## The suffix in string form
    _suffix_str     = ( '',  str( _suffix ) )[ _truncate and _suffix != False ]

    ## The suffix length
    _len_suffix     = len( _suffix_str )

    ## Whether or not we add the suffix
    _add_suffix     = ( False, True )[ _truncate and _suffix != False and _max_len > _len_suffix ]

    ## Suffix Offset
    _suffix_offset = _max_len - _len_suffix
    _suffix_offset  = ( _max_len, _suffix_offset )[ _add_suffix and _absolute_max_len != False and _suffix_offset > 0 ]

    ## The truncate point.... If not necessary, then length of string.. If necessary then the max length with or without subtracting the suffix length... Note: It may be easier ( less logic cost ) to simply add the suffix to the calculated point, then truncate - if point is negative then the suffix will be destroyed anyway.
    ## If we don't need to truncate, then the length is the length of the string.. If we do need to truncate, then the length depends on whether we add the suffix and offset the length of the suffix or not...
    _len_truncate   = ( _len, _max_len )[ _truncate ]
    _len_truncate   = ( _len_truncate, _max_len )[ _len_truncate <= _max_len ]

    ## If we add the suffix, add it... Suffix won't be added if the suffix is the same length as the text being output...
    if ( _add_suffix ):
        _text = _text[ 0 : _suffix_offset ] + _suffix_str + _text[ _suffix_offset: ]

    ## Return the text after truncating...
    return _text[ : _len_truncate ]

对于Django解决方案(问题中没有提到):

from django.utils.text import Truncator
value = Truncator(value).chars(75)

看看Truncator的源代码来理解这个问题: https://github.com/django/django/blob/master/django/utils/text.py#L66

关于Django的截断: Django HTML截断