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

シーケンスの前後のドットは、同様に構造化されているが、この 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 行のファイルが約 60,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」アプローチと呼んでいたものです。)

これに対する解決策は、ファイル オフセット値を取得するメソッドを使用して、key->offset のマッピングを作成し、Dictionary にインデックスを構築することです。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:])

これは、同様の質問に対する以前の回答とStevenHuwigの回答に基づいています。

于 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あることにも言及しています。それらはすべて同様にフォーマットされていますか?それらは異なる方法で処理する必要がありますか? それらをすべて同じ方法で処理できる場合は、それらを 1 つのフローにまとめることを検討できます。

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 に答える