【问题标题】:best way to map a value from range number in python?从python中的范围号映射值的最佳方法?
【发布时间】:2021-10-28 03:11:21
【问题描述】:

假设我们有一个这样的数据示例:

AQI LEVEL
0~50 1
51~100 2
101~150 3
151~200 4
201~300 5
>300 6

通过给定 AQI 值返回 AQI 级别的最佳方法是什么(例如:100,返回 2)

def get_level_of_aqi(aqi):
    # do sth map idea like here
    return level_of_aqi

我目前的方法:

def get_level_of_aqi(aqi):
    if 0 <= aqi <= 50:
        level = 1
    elif 51 <= aqi <= 100:
        level = 2
    ....

    return level

有没有更好的改进方法?

【问题讨论】:

  • return min((aqi+49)//50, 6)
  • @TimRoberts 不适用于 0。必须是 max(1, min((aqi+49)//50, 6))
  • @DYZ 这是一个很好的答案,而且非常接近,但由于范围的大小并不完全相同,因此可能需要在此处进行一些修改
  • @AndySu 很好,我觉得比我们三个人更多的人错过了不平等的范围

标签: python python-3.x dictionary


【解决方案1】:

鉴于范围的大小并不完全相同(对于 1-4,范围是 50,但对于 5,它是 100),您可以使用带有 sum() 的生成器表达式,如下所示:

def get_level_of_aqi(aqi):
    return sum(l<=aqi for l in [0, 51, 101, 151, 201, 301])

这利用了 True 的价值 1False 的价值 0

以下是示例输出:

In [1]: get_level_of_aqi(50)
Out[1]: 1

In [2]: get_level_of_aqi(100)
Out[2]: 2

In [3]: get_level_of_aqi(125)
Out[3]: 3

In [4]: get_level_of_aqi(220)
Out[4]: 5

In [5]: get_level_of_aqi(280)
Out[5]: 5

In [6]: get_level_of_aqi(310)
Out[6]: 6

【讨论】:

  • 我喜欢这个答案。使用此方法,您还可以创建一个包含所有范围的列表,因此如果您的范围发生变化,只需更改该列表中的值。这应该避免在链接比较的情况下会引起很多麻烦。
【解决方案2】:

看看这个实现,让我知道它是否适合你。

def get_level_of_aqi(aqi):
    if aqi > 0 and aqi <= 300:
        return (aqi-1)//50 + 1
    elif aqi >300:
        return 6
    else:
        raise Exception("Please pass positive numbers")

如果您需要对此进行解释,请在下方评论。祝你有美好的一天。

【讨论】:

  • 如果您要进行输入验证,我建议您提出ValueError,因为它更具体。然后也测试输入类型。我的意见是,要么全力以赴输入验证,要么不打扰:D
  • 我没有尝试过,但我很确定这不会为 aqi>300 返回 6...原因是代码不会到达 elif 块,因为如果 aqi > 300 为真,那么 aqi 也是 > 0. elif 块应该在 if 块之前
  • 是的,我的错,我正在更新我的代码。
  • @FoCDoT 仅供参考:范围的大小并不完全相同
【解决方案3】:

这个怎么样,它有一个字典映射。

# mapping
d = {
    1: [0, 50],
    2: [51, 100],
    3: [101, 150],
    4: [151, 200],
    5: [201, 300]
}


def get_level_of_aqi(aqi):
    if aqi < 0:
        return None

    for k, v in d.items():
        if v[0] <= aqi <= v[1]:
            return k

    return 6  # above 300


aqi = -1
level = get_level_of_aqi(aqi)
print(f'aqi: {aqi}, level: {level}')


aqi = 60
level = get_level_of_aqi(aqi)
print(f'aqi: {aqi}, level: {level}')


aqi = 500
level = get_level_of_aqi(aqi)
print(f'aqi: {aqi}, level: {level}')

# aqi: -1, level: None
# aqi: 60, level: 2
# aqi: 500, level: 6



【讨论】:

    【解决方案4】:

    如果你只想直接比较,也可以考虑使用 range()

    def get_level_of_aqi(aqi):
        if aqi in range(0, 50 + 1):
            level = 1
        elif aqi in range(51, 100 + 1):
            level = 2
        elif aqi in range(101, 150 + 1):
            level = 3
        elif aqi in range(151, 200 + 1):
            level = 4
        elif aqi in range(201, 300 + 1):
            level = 5
        elif aqi > 300:
            level = 6
        else:
            raise Exception("Please pass positive numbers")
        return level
    

    可能不花哨,但很清楚

    【讨论】:

    • 链式比较会更清晰
    • 例如,if 0 &lt;= aqi &lt;= 50if 50 &lt; aqi &lt;= 100
    【解决方案5】:
    from math import ceil
    
    
    def get_level_of_aqi(aqi: int):
        aqi = ceil((aqi or 1) / 50)
        aqi = aqi > 5 and aqi - 1 or aqi
        return min(aqi, 6)
    

    【讨论】:

      【解决方案6】:

      另一种解决方案是创建一棵二叉树,其中每个节点都包含一个值,左分支仅小于该值,右分支仅大于该值。如果您的搜索项小于/大于分支中的项,您将继续在左/右树中搜索。重复此操作,直到您无法走得更远。如果确保树是平衡的(例如,红黑树),最大搜索时间为 O(log(n))。或者,您可以使用二进制搜索。但这些解决方案只有在您拥有非常多的类别和不规则的间隔时才会奏效。

      【讨论】:

        【解决方案7】:

        从最大的数字写出你的 if 条件。

        def get_level_of_aqi(aqi):
            level = None
            if aqi > 300:
                level = 6
            elif 201 <= aqi <= 300:
                level = 5
            elif 151 <= aqi <= 200:
                level = 4
            elif 101 <= aqi <= 150:
                level = 3
            elif 51 <= aqi <= 100:
                level = 2
            elif 0 <= aqi <= 50:
                level = 1
        
            return level
        
        
        print(get_level_of_aqi(50))
        1
        print(get_level_of_aqi(52))
        2
        print(get_level_of_aqi(4555))
        6
        

        【讨论】:

          猜你喜欢
          • 2023-01-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-20
          • 1970-01-01
          相关资源
          最近更新 更多