繁体   English   中英

检查一个数字属于哪个特定范围(在许多范围内)的最pythonic方法是什么?

[英]What's the most pythonic way to check to what particular range (out of many) a number belongs?

我知道我可以通过使用 concatenated if a<X<b elif b<X<C else...来检查数字 X 是否属于特定范围(在 Y 个连续范围之外),但是是否有更简洁的 Pythonic 方式这样做?

有几种方法,这个似乎还不错:

def in_range(number : int, arange : range) -> bool:
    return number in arange

ranges = [range(6), range(4, 14), range(10, 20), range(12, 34)]
results = list(filter(lambda arange : in_range(5, arange), ranges))
print(results)

[范围(0, 6), 范围(4, 14)]

你可以像这样简化它。

def in_range(number : int, ranges : List[range]) -> List[range]:
    return [arange for arange in ranges if number in arange]

ranges = [range(6), range(4, 14), range(10, 20), range(12, 34)]
print(in_range(6, ranges))

[范围(0, 6), 范围(4, 14)]

您可能想即时了解它。

def in_range(number : int, start : int, stop : int) -> bool:
    return number in range(start,stop)

编辑 1

您也可以使用any或想要测试它的浮动,在这种情况下查看@chepner评论。

使用any

x = 57
ranges = [range(10), range(15,27), range(38,42), range(49, 63), range(70, 95)]
if any(x in range for range in ranges):
    ...

如果您不能使用range (因为您正在测试具有非整数端点的区间),请将区间存储为元组。

ranges = [(1.5, 3.7), ...]
if any(t1 < x < t2 for t1, t2 in ranges):

如果您的连续范围很密集(意味着两者之间没有间隙),我会这样做

def get_range(boundaries, x):
    for a, b in zip(boundaries, boundaries[1:]):
        if a < x < b:
            return a, b

# Test example
boundaries = [0, 5, 10, 15, 20]
x = 13
a, b = get_range(boundaries, x)
print(a, b)  # 10 15

请注意,确切的边界不包括在任何范围内。 get_range(boundaries, 10)没有找到任何范围。 要解决此问题,请将a < x < b替换为例如a <= x < b

如果您有很多范围,那么上面的内容非常好,而硬编码的if - elif链将是不切实际的。 也就是说,如果你有数百万个范围,你可能想要更聪明一点,比如实现二进制搜索。

如果您希望实现等效的 switch 语句(Python 中没有),您可以定义一个实用程序 function 以使代码更简洁和可读(即避免重复):

def switch(value):
    def inRange(a,b): 
        return a <= value and value < b
    return inRange

number = 25

case = switch(number)
if   case(10,20): print("small")
elif case(20,50): print("medium")
elif case(50,90): print("large")
else:             print("huge")  

您也可以将其与三元运算符一起使用:

inRange = switch(number)
size    = "small"  if inRange(10,20) else \
          "medium" if inRange(20,50) else \
          "large"  if inRange(50,90) else \
          "huge"

print(size)

如果您的范围是连续的,您可以避免使用二等分搜索重复上边界(这将为大型范围列表提供更好的性能):

ranges = [10,20,50,90]
sizes  = ["small","medium","large","huge"]
from bisect import bisect_right
size = sizes[bisect_right(ranges,number)-1]
print(size)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM