基本的な考え方は、レコードを削除する前に、最初にいくつのレコードを通過する必要があるかを計算することです。これは浮動小数点数でなければなりません。例えば:
percentage = 37.0
lineCount = 912.0
deleteEveryN = 100.0 / percentage # ~2.702 lines
次に、関連するすべての行を削除して、行を数えるだけです。浮動小数点を使用すると、すべてのN
行のみを削除する状況を回避できます。値によってはN-1
またはになる場合があります。N+1
countToNextDeletion = deleteEveryN / 2
foreach line:
countToNextDeletion = countToNextDeletion - 1.0
if countToNextDeletion <= 0.0:
delete line
countToNextDeletion = countToNextDeletion + deleteEveryN
countToNextDeletion
行数を半分に初期化する理由は、両端のバランスを可能な限り整えるためです (削除を中間点で対称にします)。これは、私が線画アルゴリズムで学んだトリックです (Bresenham から、記憶から)。そうしないと、削除ポイントに到達せずに最終グループで 97% しか取得できないため、期待どおりに削除できない可能性があります。
このアルゴリズムの動作は、次の Python プログラムで確認できます。
percentage = 37
lineCount = 97
deleteEveryN = 100.0 / percentage
print "Delete every %f" % deleteEveryN
delCount = 0
countToNextDeletion = deleteEveryN / 2
for n in range (lineCount):
countToNextDeletion = countToNextDeletion - 1.0
if countToNextDeletion <= 0.0:
print "Deleting %d" % n
delCount = delCount + 1
countToNextDeletion = countToNextDeletion + deleteEveryN
print "Deleted %d/%d (%f%%)" % (delCount, lineCount, delCount*100.0/lineCount)
この出力は次のとおりです (垂直方向のスペースを節約するために出力をわずかに変更します)。
pax> python testprog.py
Delete every 2.702703
Deleting 1
Deleting 4
Deleting 6
Deleting 9
Deleting 12
Deleting 14
Deleting 17
Deleting 20
Deleting 22
Deleting 25, 28, 31, 33, 36, 39, 41, 44, 47, 49, 52, 55, 58
Deleting 60, 63, 66, 68, 71, 74, 77, 79, 82, 85, 87, 90, 93
Deleting 95
Deleted 36/97 (37.113402%)
しきい値に応じて、2 行ごとに削除されることもあれば、3 行ごとに削除されることもあります (everyN
値が であるため、2 よりも 3 の方が多い2.7ish
)。
最後の行は、これが特定のデータに最適であることも示しています。
linesDeleted/lineCount percentage deltaPercentage (from 37)
====================== ========== =========================
35/97 36.0824742 0.9175258
36/97 37.1134021 0.1134021 <== closest
37/97 38.1443299 1.1443299
最初の数回の反復でどのように機能するかを示すために、最初はまたはcountToNextDeletion
に設定されています。最初の行では、 getに追加しますが、それはしきい値を超えていません。2.7027027 / 2
1.3513514
0
1
2.3513514
2 行目では、get に追加して1
しきい値を超えているので、行を削除してしきい値を引いて get にします。1
3.3513514
0.6486487
次に、しきい値を超えるまでさらに3 行かかり3.6486487
、その時点で行を削除し4
てしきい値を引いて を取得します0.945946
。
そこからあと22.945946
行で に到達し、しきい値を超えるので、削除6
してしきい値を引いて を取得します0.2432433
。
したがって、基本的には、リストを通過している場所を非常に詳細 (浮動小数点) で覚えていますが、整数の境界でのみ削除しています。