Python中的程序控制流程

时间:2009-04-16 23:41:03

标签: python list enumerate

我有一些数据存储在列表中,如果我打印出列表,我会看到以下内容:

.
.
.
007 A000000 Y
007 B000000  5
007 C010100  1
007 C020100 ACORN FUND
007 C030100 N
007 C010200  2
007 C020200 ACORN INTERNATIONAL
007 C030200 N
007 C010300  3
007 C020300 ACORN USA
007 C030300 N
007 C010400  4
.
.
.

序列之前和之后的点表示存在类似结构的其他数据但可能或可能不是该第七项(007)的一部分。如果第七项中的第一个值是'007 A000000 Y',那么我想创建一些数据项的字典列表。我可以通过运行列表中的所有项目并将它们的值与变量的某些测试值进行比较来完成此操作。例如,一行代码如:

if dataLine.find('007 B')==0:
    numberOfSeries=int(dataLine.split()[2])

我想做的是

if dataLine.find(''007 A000000 Y')==0:
    READ THE NEXT LINE RIGHT HERE

现在我不得不遍历每个周期的整个列表

我想缩短处理时间,因为我有大约60K个文件,每个文件有500到5,000行。

我考虑过创建另一个对列表的引用并计算datalines,直到dataLine.find(''007 A000000 Y')== 0。但这似乎并不是最优雅的解决方案。

5 个答案:

答案 0 :(得分:3)

您可以使用itertools.groupby()将序列细分为多个子序列。

import itertools

for key, subseq in itertools.groupby(tempans, lambda s: s.partition(' ')[0]):
    if key == '007':
    for dataLine in subseq:
        if dataLine.startswith('007 B'):
        numberOfSeries = int(dataLine.split()[2])

itertools.dropwhile()如果您真的只是想要寻找那条线,也会有效,

list(itertools.dropwhile(lambda s: s != '007 A000000 Y', tempans))
['007 A000000 Y',
 '007 B000000  5',
 '007 C010100  1',
 '007 C020100 ACORN FUND',
 '007 C030100 N',
 '007 C010200  2',
 '007 C020200 ACORN INTERNATIONAL',
 '007 C030200 N',
 '007 C010300  3',
 '007 C020300 ACORN USA',
 '007 C030300 N',
 '007 C010400  4',
 '.',
 '.',
 '.',
 '']

答案 1 :(得分:2)

您可以将数据读入字典。假设您正在读取类似文件的对象infile

from collections import defaultdict
data = defaultdict(list)
for line in infile:
    elements = line.strip().split()
    data[elements[0]].append(tuple(elements[1:]))

现在,如果您想在'007 A000000 Y'之后阅读该行,您可以这样做:

# find the index of ('A000000', 'Y')
idx = data['007'].index(('A000000', 'Y'))
# get the next line
print data['007'][idx+1]

答案 2 :(得分:2)

使用字典中的所有数据的唯一困难是,一个非常大的字典会变得麻烦。 (这就是我们以前称之为“大油矩阵”的方法。)

对此的解决方案是在Dictionary中构造索引,使用tell方法创建key-> offset的映射以获取文件偏移值。然后,您可以通过seek方法寻找再次引用该行。

答案 3 :(得分:0)

好的 - 当我谷歌搜索确保我已经覆盖了我的基地时,我遇到了一个解决方案:

我发现即使我使用它们,也忘记在列表和词典中思考。 Python有一些强大的工具来处理这些类型,以加快你操纵它们的能力 我需要一个切片,因此可以通过

轻松获得切片参考
beginPosit = tempans.index('007 A000000 Y')
endPosit = min([i for i, item in enumerate(tempans) if '008 ' in item])

其中tempans是数据主义者 现在我可以写

for line in tempans[beginPosit:endPosit]:
    process each line

我想我回答了自己的问题。我从其他答案中学到了很多,并欣赏它们,但我认为这就是我所需要的

好的,我将进一步编辑我的答案。我在这里学到了很多,但是这些东西中的一些仍然在我头脑中,我希望在我学习更多关于这个神奇工具的同时编写一些代码。

from itertools import takewhile
beginPosit = tempans.index('007 A000000 Y')
new=takewhile(lambda x: '007 ' in x, tempans[beginPosit:])

这是基于对类似问题的早期回答和Steven Huwig's回答

答案 4 :(得分:0)

你说你想这样做:

if dataLine.find(''007 A000000 Y')==0:
    READ THE NEXT LINE RIGHT HERE

据推测,这是在“for dataLine in data”循环中。

或者,您可以直接使用迭代器而不是for循环:

>>> i = iter(data)
>>> while i.next() != '007 A000000 Y': pass  # find your starting line
>>> i.next()  # read the next line
'007 B000000  5'

您还提到要处理的60K文件。它们的格式是否相似?他们需要以不同的方式处理吗?如果它们都可以以相同的方式处理,您可以考虑在一个流程中将它们链接在一起:

def gfind( directory, pattern="*" ):
    for name in fnmatch.filter( os.listdir( directory ), pattern ):
        yield os.path.join( directory, name )

def gopen( names ):
    for name in names:
        yield open(name, 'rb')

def gcat( files ):
    for file in files:
        for line in file:
            yield line

data = gcat( gopen( gfind( 'C:\datafiles', '*.dat' ) ) )

这使您可以在一个迭代器中懒惰地处理所有文件。不确定这是否有助于你当前的情况,但我认为值得一提。