用可迭代的Python对象实现类似str.strip的行为的方法

问题描述

通过Python中的str.strip()list和类似的可迭代对象,实现tuple类行为的方式是什么?

示例:

str.strip()之类的

>>> lst = ['\t','a',' ','\n','','\t']
>>> list_strip(lst)
... [0,0]
>>> list_strip(lst,elements=(0,'\t'))
... ['a']

str.lstrip()之类的

>>> lst = ['\t','\t']
>>> list_lstrip(lst)
... [0,'\t']
>>> list_lstrip(lst,'\t'))
... ['a','\t']

str.rstrip()之类的

>>> lst = ['\t','\t']
>>> list_rstrip(lst)
... ['\t',0]
>>> list_rstrip(lst,'\t'))
... ['\t','a']

实现功能的原型在下面

def set_force_iterable(val):
    if type(val) is str:
        return [val,]
    else:
        try:
            iter(val)
            return val
        except TypeError:
            return [val,]


def list_rstrip(lst,elements=None):
    '''Return a *copy* of the list or new tuple with trailing whitespace removed.

    Like :func:`str.rsrtip`.

    Parameters
    ----------
    lst : list or tuple
        List or tuple to be stripped.
    elements : iterable or None (default None)
        Elements to be stripped. Default None: strip all whitespaces.

    Returns
    -------
    list or tuple
        Return a *copy* of the list or new tuple with trailing whitespace removed.
        If elements is given and not None,remove values in elements instead.

    Examples
    --------
    >>> lst = ['\t','\t']
    >>> list_rstrip(lst)
    ... ['\t',0]
    >>> list_rstrip(lst,'\t'))
    ... ['\t','a']
    '''
    assert isinstance(lst,list) or isinstance(lst,tuple),'`lst` is not list or tuple'
    if elements is None:
        elements = (""," ","\t","\n")
    else:
        elements = set_force_iterable(elements)

    if len(lst) == 0 or (len(lst) == 1 and lst[0] in elements):
        if isinstance(lst,list):
            return []
        else:
            return ()
    else:
        if lst[-1] not in elements:
            if isinstance(lst,list):
                return lst.copy()
            else:
                return lst
        prev_will_removed = True
        for i,el in enumerate(reversed(lst)):
            if not prev_will_removed or el not in elements:
                break
        return lst[:-i]


def list_lstrip(lst,elements=None):
    '''Return a *copy* of the list or new tuple with leading whitespace removed.

    Like :func:`str.lsrtip`.

    Parameters
    ----------
    lst : list or tuple
        List or tuple to be stripped.
    elements : iterable or None (default None)
        Elements to be stripped. Default None: strip all whitespaces.

    Returns
    -------
    list or tuple
        Return a *copy* of the list or new tuple with leading whitespace removed.
        If elements is given and not None,'\t']
    >>> list_lstrip(lst)
    ... [0,'\t']
    >>> list_lstrip(lst,'\t'))
    ... ['a','\t']
    '''
    assert isinstance(lst,'`lst` is not list or tuple'

    if elements is None:
        elements = ("",list):
            return []
        else:
            return ()
    else:
        if lst[0] not in elements:
            if isinstance(lst,el in enumerate(lst):
            if not prev_will_removed or el not in elements:
                break
        return lst[i:]


def list_strip(lst,elements=None):
    '''Return a **copy** of the list or new tuple with leading and trailing whitespace removed.

    Like :func:`str.srtip`.

    Parameters
    ----------
    lst : list or tuple
        List or tuple to be stripped.
    elements : iterable or None (default None)
        Elements to be stripped. Default None: strip all whitespaces.

    Returns
    -------
    list or tuple
        Return a **copy** of the list or new tuple with leading and trailing whitespace removed.
        If elements is given and not None,'\t']
    >>> list_strip(lst)
    ... [0,0]
    >>> list_strip(lst,'\t'))
    ... ['a']
    '''
    assert isinstance(lst,list):
            return []
        else:
            return ()
    else:
        return list_lstrip(list_rstrip(lst,elements=elements),elements=elements)

解决方法

作为一种简单的替代方法,您可以使用列表切片:

def _first_index(lst):
    return next(i for i,s in enumerate(lst) if not isinstance(s,str) or (s and not s.isspace()))

def list_strip(lst):
    return lst[_first_index(lst):-_first_index(reversed(lst))]

def list_lstrip(lst):
    return lst[_first_index(lst):]

def list_rstrip(lst):
    return lst[:-_first_index(reversed(lst))]

用法:

lst = ['\t','a',' ','\n','','\t']
print(lst)
print(list_strip(lst))
print(list_lstrip(lst))
print(list_rstrip(lst))

输出:

['\t','\t']
[0,0]
[0,'\t']
['\t',0]

如果要将元素设置为手动过滤,则需要更改_find_index()中的条件,并向所有函数添加其他参数:

_fitered_chars = {""," ","\t","\n"}
def _first_index(lst,elements=_fitered_chars):
    return next(i for i,s in enumerate(lst) if s not in elements)

def list_strip(lst,elements=_fitered_chars):
    return lst[_first_index(lst,elements):-_first_index(reversed(lst),elements)]

def list_lstrip(lst,elements):]

def list_rstrip(lst,elements=_fitered_chars):
    return lst[:-_first_index(reversed(lst),elements)]

P.S。代码很清楚,但是如果您需要任何解释,请随时在注释中提问。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...