从列表中创建元组或新列表

时间:2014-01-28 19:02:14

标签: python list tuples list-comprehension

我有一个列表来自我使用非常原始的正则表达式解析的文本文件。我想重新组织一个更简洁的列表,其中只包含紧跟着日期的文件。我尝试使用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

3 个答案:

答案 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将元组展平为一个列表,以实现所需的输出。