3

ファイル名 (文字列) を保持するために、Python で循環ファイル バッファーを作成したいと考えています。バッファには次のプロパティが必要です。

  • バッファーのサイズは、名前がバッファーに格納されているファイルのサイズの合計です。バッファには最大許容サイズがあります。
  • 新しいファイルが追加されると、バッファー サイズが最大許容サイズよりも小さい場合、そのファイル名の文字列が追加されます。それ以外の場合は、変更された最も古いファイルがプッシュされ、新しいファイルが追加されます。新しく追加されたファイルが、バッファ内に既に存在するすべてのファイルよりも古い場合、何も起こりません。

そのような目的で deque を拡張することは可能ですか?

それとも最初から書くべきですか?この目的に使用できるデザインのアイデアはありますか?

ありがとう

確かに

4

2 に答える 2

4

OK、あなたの質問に対するレイモンド・ヘッティンガーの解釈は正しいと思います。あなたのコメントは、キューの長さではなく、すべてのファイルサイズの合計に関心があることを明確にしています。その方がずっと理にかなっていて、やっとあなたの言いたいことが理解できてうれしいです。heapqそれを念頭に置いて、あなたが述べたすべての要件を満たすと私が信じていることに基づいた簡単な実装を次に示します。putキューのタプルをtingして使用します。キューからアイテムを取得すると、それが最も古いファイル (つまり、タイムスタンプが最小のファイル) になることに(timestamp, filename, filesize)注意してください。get

import heapq

class FilenameQueue(object):
    def __init__(self, times_sizes_names, maxsize):
        self.maxsize = maxsize
        self.size = sum(s for t, s, n in times_sizes_names)
        self.files = list(times_sizes_names)
        heapq.heapify(self.files)
        while self.size > self.maxsize:
            self.get()
    def __len__(self):
        return len(self.files)
    def put(self, time_size_name):
        self.size += time_size_name[1]
        if self.size < self.maxsize:
            heapq.heappush(self.files, time_size_name)
        else:
            time_size_name = heapq.heappushpop(self.files, time_size_name)
            self.size -= time_size_name[1]
    def get(self):
        time_size_name = heapq.heappop(self.files)
        self.size -= time_size_name[1]
        return time_size_name

__len__キューから取得する前にキューをテストできるように、メソッドを追加しました。使用例を次に示します。

>>> f = FilenameQueue(((22, 33, 'f1'), (44, 55, 'f2'), (33, 22, 'f3')), 150)
>>> while f:
...     f.get()
... 
(22, 33, 'f1')
(33, 22, 'f3')
(44, 55, 'f2')
>>> f = FilenameQueue(((22, 33, 'f1'), (44, 55, 'f2'), (33, 22, 'f3')), 150)
>>> f.put((55, 66, 'f4'))
>>> while f:
...     f.get()
... 
(33, 22, 'f3')
(44, 55, 'f2')
(55, 66, 'f4')

Queue.PriorityQueue最適ではない完全に異なるソリューションについては、私の編集履歴を参照してください。要素を破棄するのではなく、ブロックmaxsizeすることで制限を適用することを忘れていました。それはあまり役に立ちません!

于 2012-04-16T02:19:32.710 に答える
3

私があなたの質問を正しく読んでいれば、指定された最大サイズまでのファイルの一連のファイル名が必要です。最大数を超える新しいファイルが追加された場合は、最も古いファイルを削除する必要があります。

この単純な deque ベースのクラスは、それを適切に処理する必要があります。

from collections import deque

class FileDeque(object):
    'FIFO queue of files upto a given total size'

    def __init__(self, maxsize):
        self.maxsize = maxsize
        self.d = deque()
        self.sizes = dict()
        self.currsize = 0

    def append(self, filename, filesize):
        'Add a new file to the FileDeque'
        self.d.append(filename)
        self.sizes[filename] = filesize
        self.currsize += filesize
        while self.currsize > self.maxsize and self.d:
            oldfilename = self.d.popleft()
            oldfilesize = self.sizes.pop(oldfilename)
            self.currsize -= oldfilesize

    def __iter__(self):
        'List files oldest to newest'
        return iter(self.d)

サンプル セッションは次のようになります。

>>> f = FileDeque(maxsize=10000)
>>> f.append('raptors.txt', 2500)
>>> f.append('rexes.txt', 4200)
>>> list(f)
['raptors.txt', 'rexes.txt']
>>> f.append('stegos.txt', 5000)
>>> list(f)
['rexes.txt', 'stegos.txt']
>>> f.append('brontos.txt', 500)
>>> list(f)
['rexes.txt', 'stegos.txt', 'brontos.txt']
>>> f.append('dactyls.txt', 4000)
>>> list(f)
['stegos.txt', 'brontos.txt', 'dactyls.txt']
于 2012-04-16T02:53:08.457 に答える