我想写一个逻辑来从列表中删除特定数量的行,我想尽可能均匀地选择要删除的行。当我想从列表中删除25%或50%时,这很容易,我只是编写逻辑来分别删除每一行或第二行。但是,我怎么能写出逻辑来允许我删除一个不能完全分开的数字并尽可能保持均匀间隔?
例如,在1000的列表中,我如何确定要删除哪些行以便删除尽可能均匀地说40%?我知道我有时需要删除每三行(33%),有时每隔一行(50%),但是我没有提出例程来确定要删除哪些行以便尽可能保持整个行列表。
答案 0 :(得分:0)
基本思路是首先确定在删除之前需要经过多少条记录 - 这必须是一个浮点数。例如:
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%)
你可以看到它有时会删除每一行,有时甚至每三分之一,具体取决于阈值(自everyN
值为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
最初设置为2.7027027 / 2
或1.3513514
。对于第一行0
,我们添加1
以获取2.3513514
,但不会超过阈值。
第二行1
,我们添加1
以获取 高于阈值的3.3513514
,因此我们删除该行并减去阈值以获得{{ 1}}。
然后另一个三行将我们推到阈值以上0.6486487
,此时我们删除行3.6486487
并减去阈值以获得4
}。
仅从那里获取另外两条行以达到0.945946
,超过阈值,因此我们删除2.945946
并减去阈值以获得6
。< / p>
所以基本上,你正在记住你在列表中的详细信息(浮点),但只删除整数边界。