gpt4 book ai didi

Python:有效地检查整数是否在 *many* 范围内

转载 作者:IT老高 更新时间:2023-10-28 21:45:43 30 4
gpt4 key购买 nike

我正在开发一个邮资应用程序,该应用程序需要根据多个邮政编码范围检查整数邮政编码,并根据邮政编码匹配的范围返回不同的代码。

每个代码都有多个邮政编码范围。例如,如果邮政编码在 1000-2429、2545-2575、2640-2686 或等于 2890 范围内,则应返回 M 代码。

我可以这样写:

if 1000 <= postcode <= 2429 or 2545 <= postcode <= 2575 or 2640 <= postcode <= 2686 or postcode == 2890:
return 'M'

但这似乎有很多代码行,因为有 27 个可返回代码和 77 个总范围要检查。有没有更有效(最好更简洁)的方法使用 Python 将整数与所有这些范围匹配?


编辑:有很多优秀的解决方案四处流传,所以我已经实现了所有我能做到的,并对它们的性能进行了基准测试。

这个程序的环境是一个 web 服务(实际上是由 Django 驱动的),它需要在运行中逐一检查邮政编码区域代码。那么,我的首选实现是可以快速用于每个请求的实现,并且不需要将任何进程保存在内存中,也不需要批量处理许多邮政编码。

我使用 timeit.Timer 测试了以下解决方案,默认重复 1000000 次,每次使用随机生成的邮政编码。

IF 解决方案(我的原创)

if 1000 <= postcode <= 2249 or 2555 <= postcode <= 2574 or ...:
return 'M'
if 2250 <= postcode <= 2265 or ...:
return 'N'
...

1m 代表的时间:5.11 秒。

元组中的范围 (Jeff Mercado)

在我看来更优雅一些,当然更容易输入和阅读范围。如果它们随着时间的推移而变化特别好,这是可能的。但在我的实现中它确实慢了四倍。

if any(lower <= postcode <= upper for (lower, upper) in [(1000, 2249), (2555, 2574), ...]):
return 'M'
if any(lower <= postcode <= upper for (lower, upper) in [(2250, 2265), ...]):
return 'N'
...

1m 代表的时间:19.61 秒。

设置成员资格(gnibbler)

正如作者所说,“只有构建一次集合以在循环中检查多个邮政编码时才会更好”。但我想我还是会测试一下看看。

if postcode in set(chain(*(xrange(start, end+1) for start, end in ((1000, 2249), (2555, 2574), ...)))):
return 'M'
if postcode in set(chain(*(xrange(start, end+1) for start, end in ((2250, 2265), ...)))):
return 'N'
...

1m 代表的时间:339.35 秒。

平分(罗伯特·金)

这个可能有点超出我的智力水平。我在阅读 bisect 模块方面学到了很多东西,但只是无法确定要为 find_ge() 提供哪些参数来进行可运行的测试。我希望使用许多邮政编码的循环会非常快,但如果每次都必须进行设置,则不会。因此,只有一个邮政区域代码(M具有四个范围的代码),但实际上并未运行 fast_solver:

1m 代表的时间:105.61 秒。

字典(哨兵)

使用预先生成的每个邮政区域代码的一个字典,在源文件 (106 KB) 中进行 cPickled,并为每次运行加载。我期待这种方法有更好的性能,但至少在我的系统上,IO 确实破坏了它。服务器是一款速度不快的顶级 Mac Mini。

1m 代表的时间:5895.18 秒(从 10,000 次运行推断)。

总结

好吧,我原本以为有人会给出一个我没有考虑过的简单的“呃”答案,但事实证明这要复杂得多(甚至有点争议)。

如果在这种情况下计算每一纳秒的效率,我可能会保持一个单独的进程运行,它实现了二进制搜索或 dict 解决方案之一,并将结果保存在内存中以进行极快的查找。但是,由于 IF 树只需五秒钟即可运行一百万次,这对于我的小型企业来说已经足够快了,所以我最终将在我的应用程序中使用它。

感谢大家的贡献!

最佳答案

您可以将范围放入元组并将元组放入列表中。然后使用 any() 帮助您确定您的值是否在这些范围内。

ranges = [(1000,2429), (2545,2575), (2640,2686), (2890, 2890)]
if any(lower <= postcode <= upper for (lower, upper) in ranges):
print('M')

关于Python:有效地检查整数是否在 *many* 范围内,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6053974/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com