1

行ごとに 1 つの数字を持つ大きなソート済みファイルがあります。あるサイズの各範囲の数値の数を出力したい。たとえば、範囲を 10 にして、入力を次のようにします。

1
4
34
37
42
48
53

出力は になります[2, 1, 3, 2, 2, 2, 1]。これは の長さです[1,4], [4], [34,37,42], [37,42], [42,48], [48,53], [53]。私はこれを使用して解決できると思いますdequeが、主にプログラミングの演習として、またメモリの使用量を減らすために、ファイルを 2 回開き、ファイルに 2 つの異なるポインターを持って解決しようとしています。1 つはリストの次の左端を読み取り、もう 1 つは新しい右端を読み取ります。だから私のコードは

fin1 = open(file, 'r')
fin2 = open(file, 'r')

fin1 をループすると思います。範囲が大きくなりすぎると、範囲が十分に小さくなるまで fin2 をさらに読み込み、fin1 と fin2 をステップダウンし続けます。

しかし、私はこれを機能させることができません。同じファイルに対して 2 つのファイル ハンドルを開いているのが気に入らないようです。どうすればこれを行うことができますか?

4

4 に答える 4

1

これが実装です。より良い方法があるかもしれませんが、これはうまくいくはずです。あなたが質問に投稿したのと同じ入力を想定しています。

def ranges(n):
    f = open("tmp.txt")

    while True:
        i = f.tell()
        try:
            curr = int(f.readline().rstrip())
        except ValueError:
            break  # EOF

        j = f.tell()

        while True:
            k = f.tell()  # End of range location
            try:
                next = int(f.readline().rstrip())
            except ValueError:
                break  # EOF

            if next < n or (next - curr) < n:
                continue
            else:
                break

        f.seek(i)  # Go to beginning of range

        r = []
        while f.tell() < k:
            r.append(int(f.readline().strip()))
        print(r)

        f.seek(j)  # Go to line after beginning of range


>>> ranges(10)
[1, 4]
[4]
[34, 37, 42]
[42, 48]
[48, 53]
[53]
于 2013-07-31T18:30:46.790 に答える
1

EDIT:私の以前の実装はdequeソリューションです(完全なものではありません)。2つのファイルポインターを使用したソリューションは次のとおりです。

def sliding_ranges(filename=r"C:\Temp\data.txt", N=10):
    f1, f2 = open(filename), open(filename)
    k, res, i1, i2, r1, r2 = 1, [], 0, 0, 1, 1
    while True:
        while r2 and (not i2 or i2 - i1 < N):
            r2, k = f2.readline(), k + 1
            if r2: i2 = int(r2)

        while r1 and (not i1 or not r2 or i2 - i1 > N):
            r1, k = f1.readline(), k - 1
            if i1: res.append(k)
            if r1: i1 = int(r1)

        if not r1: break

    return res

    >>> sliding_ranges(r"C:\Temp\data.txt", 10)
    [2, 1, 3, 2, 2, 2, 1]

PREVIOUS: これはワンパスでの実装です。トラバースしている間、リストの長さを数え続けます

f = open(r"d:\temp\data.txt")

d, res, N = [], {}, 10
for j in f:
    i = int(j)
    if i not in res: res[i] = 1
    for k, v in res.items():
        if i - k > N:
            d.append(v)
            del res[k]
        elif k != i:
            res[k] += 1 
d = d + [v for v in res.values()]

各反復のオブジェクトのリストは次のとおりです

d []
res {}

d []
res {1: 1}

d []
res {1: 2, 4: 1}

d [2, 1]
res {34: 1}

d [2, 1]
res {34: 2, 37: 1}

d [2, 1]
res {34: 3, 42: 1, 37: 2}

d [2, 1, 3, 2]
res {42: 2, 48: 1}

d = [2, 1, 3, 2, 2, 2, 1]
于 2013-07-31T18:35:06.260 に答える
0

なぜこのようにしているのかわかりませんが、あなたの質問 (値のカウントではなくファイル I/O に関するものです) に答えるには、1 つのファイル ハンドルと 2 つのファイル ポインターが必要です。

ファイル ハンドルfでファイルを開くと、 はファイルf.tell()内の位置を通知しf.seek(pos)、ポインタを指定された位置に戻します。

f.seek(pos,how)オプションの 2 番目のパラメーターを使用すると、シークの計算方法にある程度の柔軟性が得られます (howファイルの先頭からのシークを 0、現在の位置からのシークを 1、最後からのシークを 2 に設定)。これによりpos、厳密に最初からではなく、参照からのオフセットとして使用できます。

于 2013-07-31T18:23:47.360 に答える