質問

リストに保存したデータがあり、リストを印刷すると次のように表示されます。

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

シーケンスの前後のドットは、同様に構造化されているが、この 7 番目の項目 (007) の一部である場合とそうでない他のデータがあることを表します。7 番目の項目の最初の値が「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

現在、サイクルごとにリスト全体を反復処理する必要があります

それぞれに 500 ~ 5,000 行のファイルが約 60K あるため、処理を短縮したいと考えています。

リストへの別の参照を作成し、dataLine.find(''007 A000000 Y')==0 になるまでデータ行をカウントすることを考えました。しかし、それが最もエレガントな解決策であるとは思えません。

役に立ちましたか?

解決 5

さて、基本をカバーしたかどうかを確認するためにグーグルで検索しているときに、解決策を見つけました。

リストや辞書は使っているのに、それを使って考えることを忘れてしまうことがあります。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:])

これは、同様の質問に対する以前の回答に基づいています。 スティーブン・ヒューイグの 答え

他のヒント

あなたは、複数のサブシーケンスに分割するようにあなたの順序を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',
 '.',
 '.',
 '.',
 '']

あなたは辞書にデータを読み取ることができます。あなたはファイルライクオブジェクト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]

辞書内のすべてのデータを使用しての唯一の難点は、本当に大きな辞書が面倒になることができるということです。 (それは、私たちは「ビッグオレマトリックス」のアプローチを呼び出すために使用したものです。)

この解決策は、辞書のインデックスを構築することで、KEY-のマッピングを作成する>ファイルオフセット値を取得するtell法を用いて、オフセット。そして、あなたはseek方法で求めることにより、再びラインを参照することができます。

あなたはこれをやってみたかったと述べます:

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

おそらくこれは、「データラインのデータの」ループ内である。

また、あなたが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' ) ) )

これは、あなたが遅延し、単一のイテレータ内のすべてのファイルを処理することができます。わからないことは、あなたの現在の状況に役立ちますが、私は言及することは価値があると思った場合。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top