我有一个列表来自我使用非常原始的正则表达式解析的文本文件。我想重新组织一个更简洁的列表,其中只包含紧跟着日期的文件。我尝试使用len()循环遍历列表,但这只会提取文件而不是下一个条目。非常感谢提前。
此:
2014-01-28
part002.csv.gz
2014-01-28
part001.csv.gz
2014-01-28
2014-01-28
2014-01-27
2014-01-27
2014-01-26
2014-01-26
2014-01-25
part002.csv.gz
2014-01-25
成为这个:
part002.csv.gz
2014-01-28
part001.csv.gz
2014-01-28
part002.csv.gz
2014-01-25
答案 0 :(得分:1)
您可以使用列表理解:
filtered = [e for i, e in enumerate(l) if not isDate(e) or (i > 0 and not isDate(l[i-1]))]
完整示例:
l = ['2014-01-28', 'part002.csv.gz', '2014-01-28', 'part001.csv.gz', '2014-01-28', '2014-01-28', '2014-01-27', 'part002.csv.gz', '2014-01-25']
def isDate (s):
return '.' not in s
filtered = [e for i, e in enumerate(l) if not isDate(e) or (i > 0 and not isDate(l[i-1]))]
print (filtered)
说明:
l
是我们的原始列表。
isDate
接受一个字符串并测试它是否是一个日期(在我的简单示例中,它仅检查它是否包含句点,以获得更好的结果使用正则表达式或strptime)。
enumerate
列举一个列表(或任何可迭代的,我现在将坚持单词list
,只是为了不太技术化)。它返回一个元组列表;每个包含索引的元组和传递给枚举的列表元素。例如,enumerate (['a', None, 3])
生成[(0,'a'),(1,None),(2,3)]
i, e =
解包元组,将索引分配给i
,将元素分配给e
。
列表理解就像这样(简单地说):[x for x in somewhere if cond(x)]
返回符合条件somewhere
的{{1}}所有元素的列表。
在我们的案例中,我们只添加元素到我们的过滤列表,如果它们不是日期(不是水果)cond(x)
,或者它们不在开头not isDate(e)
,同时它们的前身是不是日期i > 0
(即文件)。
在伪代码中:
not isDate(l[i-1])
答案 1 :(得分:0)
将前一行存储在每一行,然后在需要时随时存放
previous_line = None
newlist = []
for line in lines:
if isdate(line):
newlist.append(previous_line)
previous_line = line
定义isdate
:
import datetime
def isdate(s):
try:
datetime.datetime.strptime(s, '%Y-%m-%d')
except:
return False
else:
return True
答案 2 :(得分:0)
完成它:
s = """
#that long string, snipped
"""
li = [x for x in s.splitlines() if x]
li
Out[3]:
['2014-01-28',
'part002.csv.gz',
'2014-01-28',
'part001.csv.gz',
'2014-01-28',
'2014-01-28',
'2014-01-27',
'2014-01-27',
'2014-01-26',
'2014-01-26',
'2014-01-25',
'part002.csv.gz',
'2014-01-25']
[tup for tup in zip(li,li[1:]) if 'csv' in tup[0]] #shown for dicactic purposes, gen expression used below
Out[7]:
[('part002.csv.gz', '2014-01-28'),
('part001.csv.gz', '2014-01-28'),
('part002.csv.gz', '2014-01-25')]
实际答案:
from itertools import chain
list(chain.from_iterable(tup for tup in zip(li,li[1:]) if 'csv' in tup[0]))
Out[9]:
['part002.csv.gz',
'2014-01-28',
'part001.csv.gz',
'2014-01-28',
'part002.csv.gz',
'2014-01-25']
基本上:zip
(在python 2中,使用izip
)列表与自身一起,一个索引提前。迭代成对元组,过滤掉那些没有类似文件字符串的第一个元素。最后,使用itertools.chain
将元组展平为一个列表,以实现所需的输出。