【发布时间】:2022-01-27 04:24:22
【问题描述】:
我正在寻找一个函数来使列表尽可能地未排序。最好在 Python 中。
背景故事:
我想检查 URL 状态并查看 URL 是否给出 404。我只使用
asyncio
和
requests
模块。没什么特别的。
现在我不想让服务器过载,所以我想尽量减少同时检查同一域中的 URL。我的想法是对 URL 进行排序,使彼此接近的项目(具有相同的排序键 = 域名)在列表中尽可能远离。
数字示例:
a=[1,1,2,3,3] # <== sorted list, sortness score = 2
0,1,2,3,4 # <== positions
可能未排序为:
b=[1,3,2,1,3] # <== unsorted list, sortness score = 6
0,1,2,3,4 # <== positions
我想说,我们可以通过将相等项目(具有相同的键 = 域名)之间的距离相加来计算排序分数。更高的排序意味着更好的未排序。也许有更好的方法来测试 unsortness。
列表
a
的排序分数为 2。1 的距离总和为 (1-0)=1,2 为 0,3 为 (4-3)=1。
列表
b
的排序分数为 6。1 的距离总和为 (3-0)=3,2 为 0,3 为 (4-1)=3。
URL 列表看起来像(域,URL)元组列表:
[
('example.com', 'http://example.com/404'),
('test.com', 'http://test.com/404'),
('test.com', 'http://test.com/405'),
('example.com', 'http://example.com/405'),
...
]
我正在开发一个可以正常工作的原型,但不是最佳的,因为我可以找到一些最好手动未分类的变体。
有人想试试吗?
This is my code ,但不是很好:):
from collections import Counter
from collections import defaultdict
import math
def test_unsortness(lst:list) -> float:
pos = defaultdict(list)
score = 0
# Store positions for each key
# input = [1,3,2,3,1] => {1: [0, 4], 3: [1, 3], 2: [2]}
for c,l in enumerate(lst):
pos[l].append(c)
for k,poslst in pos.items():
for i in range(len(poslst)-1):
score += math.sqrt(poslst[i+1] - poslst[i])
return score
def unsort(lst:list) -> list:
free_positions = list(range(0,len(lst)))
output_list = [None] * len(free_positions)
for val, count in Counter(lst).most_common():
pos = 0
step = len(free_positions) / count
for i in range(count):
output_list[free_positions[int(pos)]] = val
free_positions[int(pos)] = None # Remove position later
pos = pos + step
free_positions = [p for p in free_positions if p]
return output_list
lsts = list()
lsts.append( [1,1,2,3,3] )
lsts.append( [1,3,2,3,1] ) # This has the worst score after unsort()
lsts.append( [1,2,3,0,1,2,3] ) # This has the worst score after unsort()
lsts.append( [3,2,1,0,1,2,3] ) # This has the worst score after unsort()
lsts.append( [3,2,1,3,1,2,3] ) # This has the worst score after unsort()
lsts.append( [1,2,3,4,5] )
for lst in lsts:
ulst = unsort(lst)
print( ( lst, '%.2f'%test_unsortness(lst), '====>', ulst, '%.2f'%test_unsortness(ulst), ) )
# Original score Unsorted score
# ------- ----- -------- -----
# ([1, 1, 2, 3, 3], '2.00', '====>', [1, 3, 1, 3, 2], '2.83')
# ([1, 3, 2, 3, 1], '3.41', '====>', [1, 3, 1, 3, 2], '2.83')
# ([1, 2, 3, 0, 1, 2, 3], '6.00', '====>', [1, 2, 3, 1, 2, 3, 0], '5.20')
# ([3, 2, 1, 0, 1, 2, 3], '5.86', '====>', [3, 2, 1, 3, 2, 1, 0], '5.20')
# ([3, 2, 1, 3, 1, 2, 3], '6.88', '====>', [3, 2, 3, 1, 3, 2, 1], '6.56')
# ([1, 2, 3, 4, 5], '0.00', '====>', [1, 2, 3, 4, 5], '0.00')
附言。我不只是在寻找随机化功能,而且我知道有可以管理域负载的爬虫,但这是为了练习。
-
令人惊讶的是,有一个问题似乎与此主题完全相关 cs.stackexchange.com/questions/11836/how-to-measure-sortedness
-
您将 URL 粘贴在字典中如何(多映射、列表列表、使用域名作为键),然后线性地遍历键,沿途删除项目?跨度>
-
我同意@FilipMilovanović,循环法似乎最简单
-
您的“未分类”分数是否代表了您的真正目标,还是只是方便?在实际查询域时,
[3, 2, 1, 0, 1, 2, 3]
的模式真的比[1, 2, 3, 0, 1, 2, 3]
更好吗?如果目标是“传播事物”,那么将 100 和 50 的 1 分开可能比每个约 3 的 51 更差,尽管两者都是 150 与您的文本度量。 (当然,您可以找到更好的设置,但查看极端情况可以帮助衡量指标是否指定错误。)- P.S. “排序”在这里有点用词不当,因为您并不真正关心总排序。