使用iterable Python对象实现类似str.strip()行为的方法

使用iterable Python对象实现类似str.strip()行为的方法,python,list,tuples,strip,python-collections,Python,List,Tuples,Strip,Python Collections,用Python中的list、tuple和类似的iterable对象实现类似str.strip()的行为的方法是什么 示例: str.strip()-like >>> lst = ['\t', 0, 'a', ' ', 0, '\n', '\n', '', '\t'] >>> list_strip(lst) ... [0, 'a', ' ', 0] >>> list_strip(lst, elements=(0, '\n', '', ' ',

用Python中的
list
tuple
和类似的iterable对象实现类似
str.strip()
的行为的方法是什么

示例:

str.strip()
-like

>>> lst = ['\t', 0, 'a', ' ', 0, '\n', '\n', '', '\t']
>>> list_strip(lst)
... [0, 'a', ' ', 0]
>>> list_strip(lst, elements=(0, '\n', '', ' ', '\t'))
... ['a']
>>> lst = ['\t', 0, 'a', ' ', 0, '\n', '\n', '', '\t']
>>> list_lstrip(lst)
... [0, 'a', ' ', 0, '\n', '\n', '', '\t']
>>> list_lstrip(lst, elements=(0, '\n', '', ' ', '\t'))
... ['a', ' ', 0, '\n', '\n', '', '\t']
>>> lst = ['\t', 0, 'a', ' ', 0, '\n', '\n', '', '\t']
>>> list_rstrip(lst)
... ['\t', 0, 'a', ' ', 0]
>>> list_rstrip(lst, elements=(0, '\n', '', ' ', '\t'))
... ['\t', 0, 'a']
str.lstrip()
-like

>>> lst = ['\t', 0, 'a', ' ', 0, '\n', '\n', '', '\t']
>>> list_strip(lst)
... [0, 'a', ' ', 0]
>>> list_strip(lst, elements=(0, '\n', '', ' ', '\t'))
... ['a']
>>> lst = ['\t', 0, 'a', ' ', 0, '\n', '\n', '', '\t']
>>> list_lstrip(lst)
... [0, 'a', ' ', 0, '\n', '\n', '', '\t']
>>> list_lstrip(lst, elements=(0, '\n', '', ' ', '\t'))
... ['a', ' ', 0, '\n', '\n', '', '\t']
>>> lst = ['\t', 0, 'a', ' ', 0, '\n', '\n', '', '\t']
>>> list_rstrip(lst)
... ['\t', 0, 'a', ' ', 0]
>>> list_rstrip(lst, elements=(0, '\n', '', ' ', '\t'))
... ['\t', 0, 'a']
str.rstrip()
-like

>>> lst = ['\t', 0, 'a', ' ', 0, '\n', '\n', '', '\t']
>>> list_strip(lst)
... [0, 'a', ' ', 0]
>>> list_strip(lst, elements=(0, '\n', '', ' ', '\t'))
... ['a']
>>> lst = ['\t', 0, 'a', ' ', 0, '\n', '\n', '', '\t']
>>> list_lstrip(lst)
... [0, 'a', ' ', 0, '\n', '\n', '', '\t']
>>> list_lstrip(lst, elements=(0, '\n', '', ' ', '\t'))
... ['a', ' ', 0, '\n', '\n', '', '\t']
>>> lst = ['\t', 0, 'a', ' ', 0, '\n', '\n', '', '\t']
>>> list_rstrip(lst)
... ['\t', 0, 'a', ' ', 0]
>>> list_rstrip(lst, elements=(0, '\n', '', ' ', '\t'))
... ['\t', 0, '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', 0, 'a', ' ', 0, '\n', '\n', '', '\t']
    >>> list_rstrip(lst)
    ... ['\t', 0, 'a', ' ', 0]
    >>> list_rstrip(lst, elements=(0, '\n', '', ' ', '\t'))
    ... ['\t', 0, '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, remove values in elements instead.

    Examples
    --------
    >>> lst = ['\t', 0, 'a', ' ', 0, '\n', '\n', '', '\t']
    >>> list_lstrip(lst)
    ... [0, 'a', ' ', 0, '\n', '\n', '', '\t']
    >>> list_lstrip(lst, elements=(0, '\n', '', ' ', '\t'))
    ... ['a', ' ', 0, '\n', '\n', '', '\t']
    '''
    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[0] not in elements:
            if isinstance(lst, list):
                return lst.copy()
            else:
                return lst
        prev_will_removed = True
        for i, 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, remove values in elements instead.

    Examples
    --------
    >>> lst = ['\t', 0, 'a', ' ', 0, '\n', '\n', '', '\t']
    >>> list_strip(lst)
    ... [0, 'a', ' ', 0]
    >>> list_strip(lst, elements=(0, '\n', '', ' ', '\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:
        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', 0, 'a', ' ', 0, '\n', '\n', '', '\t']
print(lst)
print(list_strip(lst))
print(list_lstrip(lst))
print(list_rstrip(lst))
输出:

['\t', 0, 'a', ' ', 0, '\n', '\n', '', '\t']
[0, 'a', ' ', 0]
[0, 'a', ' ', 0, '\n', '\n', '', '\t']
['\t', 0, 'a', ' ', 0]

如果要将元素设置为手动筛选,则需要更改
\u find\u 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=_fitered_chars):
    return lst[_first_index(lst, elements):]

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

附加说明代码非常清楚,但如果您需要任何解释,请随时在评论中询问。

“最具pythonic”将以观点为基础。您当前的实现是否有需要解决的问题?我不确定是否有“经典方法”,这是一项具体的任务,有许多不同的方法可以解决。我可能会从
l[next(index for index,value in enumerate(l)if value):]
开始,然后从那里开始添加行为(例如,在没有任何真值的情况下处理输入,对值应用一些转换…)。我想,您可以应用
itertools.dropwhile()
。现在还不清楚真正的问题是什么。问题已经包括问题陈述的工作解决方案。如果它们不起作用,问题应该澄清它们不起作用的程度,包括给定输入的实际输出和期望输出。如果它们确实起作用,问题应该澄清解决方案还必须提供什么,以区别于问题中提出的解决方案。@Chris_Rands:我不同意。这与其说是一个范围很广的重点编码问题,不如说是一个代码审查问题。