【问题标题】:Changing Elif Statement to "Python-Like" Code将 Elif 语句更改为“类 Python”代码
【发布时间】:2019-11-26 15:15:49
【问题描述】:

我理解 Python 的核心在于效率。 我将如何编写下面的代码以使其更具 Pythonic?

我想过使用字典,但由于elif 语句的条件是范围,我认为这是不可能的。

threshold_scale
if pop in range(threshold_scale[0], threshold_scale[1]):
    color = '#ff0000'
elif pop in range(threshold_scale[1], threshold_scale[2]):
    color = '#f6ff00'
elif pop in range(threshold_scale[2], threshold_scale[3]):
    color = '#00ff08'
elif pop in range(threshold_scale[3], threshold_scale[4]):
    color = '#0d00ff'
elif pop in range(threshold_scale[4], threshold_scale[5]+1):
    color = '#ff00f7'

输出

[1960, 648065, 1294170, 1940275, 2586380, 3232486]

【问题讨论】:

  • “Python 就是为了效率” ??从何时起?您发布的代码有什么问题?
  • 效率方面,这段代码没有任何问题。 in range(...) 是 O(1) 检查,elif 确保只进行最少数量的检查。
  • 而且,FWIW,range 对象可散列的,因此它们可以用作字典键
  • 我认为字典在这里是个不错的选择。
  • 我不知道范围可以在字典中使用,因为我找到的所有字典示例都使用字符串对象。谢谢你告诉我。

标签: python python-3.x dictionary if-statement


【解决方案1】:

interval tree 专为这些类型的查询而设计。一个例子是intervaltree 模块。

from intervaltree import IntervalTree, Interval

threshold_scale = [1960, 648065, 1294170, 1940275, 2586380, 3232486]

ranges = zip(threshold_scale, threshold_scale[1:])
colors = ["#ff0000", "#f6ff00", "$00ff08", "$0d00ff", "$ff00f7"]

t = IntervalTree([Interval(x, y, c) for (x,y), c in zip(ranges, colors)])

pop = 2000

color = sorted(t[2000])[0].data

对于n区间,构建区间树需要O(n lg n),单个查询需要O(lg n)时间。 (从技术上讲,它是O(lg n + m),其中m 是结果中的项目数。不过,我们的树由不重叠的范围组成,因此m 始终等于1。)

相比之下,您的if 语句将花费O(n) 时间。每个pop in range(...) 都需要O(1) 时间,但其中可能有O(n)。如果您需要针对同一组区间进行多次查询,则使用区间树会更快。

【讨论】:

    【解决方案2】:
    colors = [
        '#ff0000',
        '#f6ff00',
        '#00ff08',
        '#0d00ff',
        '#ff00f7',
    ]
    color = next(c for c, t_range in
                 zip(colors, zip(threshold_scale, threshold_scale[1:])) if
                 pop in range(*t_range))
    

    给定输入:

    threshold_scale = [0,2,4,6,8,10]
    pop = 7
    

    输出:

    f6ff00
    

    【讨论】:

      【解决方案3】:

      您可以使用numpy.digitize

      import numpy as np
      
      threshold_scale = [1960, 648065, 1294170, 1940275, 2586380, 3232486]
      
      pop = [2000, 2000000, 2800000]
      
      color = np.array(['#ff0000', '#f6ff00', '#00ff08', '#0d00ff', '#ff00f7'])
      
      color[np.digitize(pop, threshold_scale) - 1]
      

      您也必须处理覆盖范围之外的弹出值...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-02
        • 1970-01-01
        • 2020-10-28
        • 2015-01-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多