很抱歉,标题令人困惑,但是在一行之内描述问题有点困难。所以我有一个看起来像这样的列表:
['','','','A','','','B','','C','','D','','','']
我想得到这样的东西:
['A','','','B','C','D']
过程: 1.删除所有开头和结尾的空字符串(A之前和D之后的字符串)。 2.删除夹在非空字符串(例如B&C和C&D之间的单个)之间的单个空字符串。但是,如果将多于一个的空字符串夹在中间,请将其保留(例如A和B之间的2个)。
有人可以帮我解决这个问题吗?提前非常感谢您!
答案 0 :(得分:3)
这是一种可能的解决方案。您可以使用itertools.groupby
来标识相同字符串的运行,并计算一行中出现的数量:
>>> import itertools
>>> seq = ['','','','A','','','B','','C','','D','','','']
>>> runs = [(c, len(list(g))) for c,g in itertools.groupby(seq)]
>>> runs
[('', 3), ('A', 1), ('', 2), ('B', 1), ('', 1), ('C', 1), ('', 1), ('D', 1), ('', 3)]
然后删除第一个和最后一个为空字符串的元素:
>>> if runs[0][0] == '': runs = runs[1:]
...
>>> if runs[-1][0] == '': runs = runs[:-1]
...
>>> runs
[('A', 1), ('', 2), ('B', 1), ('', 1), ('C', 1), ('', 1), ('D', 1)]
然后删除由一个空字符串组成的所有内部组:
>>> runs = [(char, count) for char, count in runs if not (char == '' and count == 1)]
>>> runs
[('A', 1), ('', 2), ('B', 1), ('C', 1), ('D', 1)]
然后将这些运行重新分配到一个平面列表中。
>>> result = [char for char, count in runs for _ in range(count)]
>>> result
['A', '', '', 'B', 'C', 'D']
答案 1 :(得分:2)
这是一个并非在所有情况下都有效的答案,但如果您可以识别出列表中不存在 的字符,该答案将起作用。通常的想法是加入列表,剥离,替换元素的单次运行,然后在元素上拆分:
设置
L = ['', '', '', 'A', '', '', 'B', '', 'C', '', 'D', '', '', '']
import re
re.sub(r'(?<!@)@@(?!@)', r'@', '@'.join(L).strip('@')).split('@')
['A', '', '', 'B', 'C', 'D']
将其包装在函数中并断言el
元素有效:
def custom_stripper(L, el):
"""
Strips empty elements from start/end of a list,
and removes single empty whitespace runs
Parameters
----------
L: iterable, required
The list to modify
el: str, required
An element found nowhere in the joined list
Returns
-------
A properly formatted list
"""
assert(el not in ''.join(L))
rgx = r'(?<!{el}){el}{el}(?!{el})'.format(el=el)
return re.sub(rgx, el, el.join(L).strip(el)).split(el)
>>> custom_stripper(L, '@')
['A', '', '', 'B', 'C', 'D']
>>> custom_stripper(L, 'A')
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-161-7afa6741e503> in <module>()
----> 1 custom_stripper(L, 'A')
<ipython-input-158-606893c3fe1c> in custom_stripper(L, el)
11 """
12
---> 13 assert(el not in ''.join(L))
14 rgx = r'(?<!{el}){el}{el}(?!{el})'.format(el=el)
15
AssertionError:
要对此进行细分:
>>> '@'.join(L).strip('@')
'A@@@B@@C@@D'
>>> re.sub(r'(?<!@)@@(?!@)', r'@', 'A@@@B@@C@@D')
'A@@@B@C@D'
>>> 'A@@@B@C@D'.split('@')
['A', '', '', 'B', 'C', 'D']
正则表达式说明
替换是关键,因为替换允许连续替换两个@
(表示列表中仅存在一个空字符串的位置)。但是,必须注意不要在另一行@
内连续替换两个@
(例如,如果连续有两个空字符串)。这里的关键是否定的向前/向后看。
(?<! # Negative lookbehind
@ # Asserts string *does not* match @
)
@@ # Matches @@
(?! # Negative lookahead
@ # Asserts string *does not* match @
)