1

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

.
.
.
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 行。

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

4

5 回答 5

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',
 '.',
 '.',
 '.',
 '']
于 2009-04-17T01:35:02.433 回答
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]
于 2009-04-17T00:00:22.580 回答
2

使用字典中的所有数据的唯一困难是,一个非常大的字典可能会变得很麻烦。(这就是我们过去所说的“Big Ole Matrix”方法。)

解决这个问题的方法是在Dictionary中构造一个索引,创建key->offset的映射,使用tell方法获取文件偏移值。然后你可以通过seek方法搜索再次参考该行。

于 2009-04-17T00:06:13.050 回答
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 的回答

于 2009-04-17T19:14:06.770 回答
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' ) ) )

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

于 2009-04-17T19:33:11.513 回答