草庐IT

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

coder 2023-05-22 原文

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

每个代码都有多个邮政编码范围。例如,如果邮政编码在 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/

有关Python:有效地检查整数是否在 *many* 范围内的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  3. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  4. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  5. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  6. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

  7. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  8. ruby - 如何进行排列以有效地定制输出 - 2

    这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][

  9. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  10. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

随机推荐