2012-04-16 11 views
2

私は、ファイル名(文字列)を保持するために、Pythonで循環ファイルバッファを構築したいと考えています。バッファには、次のプロパティが必要です。collections.dequeを拡張して "ファイルバッファ"を構築できますか?

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

このような目的でデキューを拡張することはできますか?

また、最初から書き込む必要がありますか?この目的のために使用できる設計アイデアはありますか?

おかげ

スレシュ

+1

両端キューが自動的にオブジェクトを破棄 'maxlen'性質を持っているん:

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) 

サンプル・セッションは、このようになります。キューのもう一方の端から – Darthfett

+0

このリストの有効期間中にこれらのファイルの変更を計画していますか(「最も古い変更ファイルは「最新の変更ファイル」になる可能性があります)? また、「バッファに既に存在するすべてのファイルよりも古いファイル」を追加すると、キュー内のファイル数が減少するか、ファイルを無視しますか? – Darthfett

+1

最大サイズはファイル名の長さによって異なるはずですか?ファイル名の_番号?ファイル名が参照するファイルの_size_? – agf

答えて

4

OK、私はあなたの質問のレイモンドヘッティンガーの解釈が正しいと信じている、とあなたのコメントは、キューの長さに関係じゃないことを明確にではなく、としていますすべてのファイルサイズの合計。それははるかに意味がある、と私は最終的にあなたが意味するものを理解してうれしいです。これを念頭に置いて、私があなたのすべての要求を満たすと信じているheapqに基づく簡単な実装をここに示します。キュー上のputティン(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は、要素を破棄するのではなく、ブロック制限によって制限を適用することを忘れていました。それほど有用ではありません!

+0

ファイル名の数ではなく、長さの合計の点で 'maxlen'を持つことを望んでいることを除いて、手動で実装する必要があります。 'deque'が優先順位でソートされないので、あなたはO(n)の削除で終わります。あなたは確かにこれのためのキューのいくつかの種類が必要です。 – agf

+0

@ agf、私は彼が 'maxlen'をファイル名の長さの合計にしたいと誤解していたと仮定しています。私はそれが何であるかを想像することはできません。そして、あなたの2番目のポイントは、私が 'PriorityQueue'sを述べた理由です。 – senderle

+0

ニース編集。あなたは正しい、それは本当に意味をなさない。私の新しい推測 - 彼は、ファイル名で参照される_ファイルのサイズを意味しました。 – agf

2

質問を正しく読んでいる場合は、指定された最大サイズまでファイルのファイル名のシーケンスが必要です。新しいファイルが最大値を超えて追加された場合、最も古いファイルを忘れてしまいます。

この単純な両端キューベースのクラスはうまくそれの世話をする必要があります。

>>> 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'] 
+0

私は彼がFIFOを望んでいるとは思っていませんが、彼は最後に変更された時間に最小優先度を求めています。 – agf

関連する問題