【问题标题】:Turning a function with multiple if else statement into a dictionary将具有多个 if else 语句的函数转换为字典
【发布时间】:2018-03-15 00:21:59
【问题描述】:

所以我目前有一个功能可以输出输入高度的音障。

def soundbarier (y):   
    if 0 < y < 1524:
        S = 340.3
    elif 1524 < y < 3048:
        S = 334.4
    elif 3048 < y < 4572:
        S = 328.4
    elif 4572 < y < 6096:
        S = 322.2
    elif 6096 < y < 7620:
        S = 316.0
    elif 7620 < y < 9144:
        S = 309.6
    elif 9144 < y < 10668:
        S = 303.6
    elif 10668 < y < 12192:
        S = 295.4
    else:
        S = 294.5
    return (float(S))

我想用字典来缩短它,但我不能让它工作。

def SOUND(y):
    return {
    0 < float(y) < 1524: 340.3,
    1524 < y < 3048: 334.4,
    3048 < y < 4572: 328.4,
    4572 < y < 6096: 322.2,
    6096 < y < 7620: 316.0,
    7620 < y < 9144: 309.6,
    9144 < y < 10668: 303.6,
    10668 < y < 12192: 295.4
    }.get(y, 9)

print(SOUND(1500))

我真的不想要任何默认值。我怎样才能让它工作?我基本上需要该函数为某个范围内的某个 Y 输出 S。

【问题讨论】:

  • 外部模块可以吗?
  • 你能详细说明吗?
  • pandas 有一个名为 IntervalIndex 的 API,它以对数时间构建树和索引。您还可以一次查询具有多个值的树。
  • 那么不,我不熟悉外部模块。我想我被那个丑陋的功能所困扰吧?
  • 不是一个通用的解决方案,但由于您的间隔以 1524 的倍数增加,您可以只除以 1524,四舍五入并使用该数字作为您的密钥。

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


【解决方案1】:

Mathemagic by @Tim.

consts = [340.3, 334.4, 328.4, 322.2, 316.0, 309.6, 303.6, 295.4, 295.5]

def soundbarrier(y):
    return consts[
        -1 if (not (0 < y < 12192) or y % 1524 == 0) else y // 1524
    ]

In [1]: soundbarrier(1500)
Out[1]: 340.3

In [2]: soundbarrier(10000)
Out[2]: 303.6

In [3]: soundbarrier(100)
Out[3]: 340.3

In [4]: soundbarrier(1524)
Out[4]: 295.5

【讨论】:

  • 所以它只是碰巧以这种方式工作,因为我的身高每次都增加相同的因素?否则它不会工作?
  • @user3613025 这就是现实情况,是的。
  • 这与我的程序完美配合。感谢所有帮助贡献的人。
【解决方案2】:

对此没有内置语法,但您可以使用 'bisect' 有效地实现它,它会为您在列表中找到数字的位置。

def soundbar(y):
  barrier_dict = {
    1524: 340.0,
    3048: 334.4,
    4572: 328.4,
    float('inf'): 0
  }
  height, barrier = zip(*sorted(barrier_dict.items()))
  return barrier[bisect(height, y)]

print 1000, '->', soundbar(1000)
print 2000, '->', soundbar(2000)
print 2500, '->', soundbar(2500)
print 10000, '->', soundbar(10000)

输出:

1000 -> 340.0
2000 -> 334.4
2500 -> 334.4
10000 -> 0

【讨论】:

  • 为什么要以dict 开头呢?
【解决方案3】:

一个通用的解决方案是使用numpy.digitize 结合字典。

请注意,这并不处理输入位于边界上的边缘情况,在这种情况下floating point approximations 可能需要特别注意。

import numpy

def SOUND(y):

    bins = np.array([0, 1524, 3048, 4572, 6096, 7620, 9144, 10668, 12192])
    values = np.array([340.3, 334.4, 328.4, 322.2, 316.0, 309.6, 303.6, 295.4])

    d = dict(enumerate(values, 1))

    return d[int(np.digitize(y, bins))]

SOUND(7200)  # 316.0

【讨论】:

  • 我不熟悉numpy.digitize。我基本上有 2 组列表将通过这个音障功能运行,如果在某个 y 的任何点,我的速度大于 S,那么它将输出“音障损坏”消息。这适用于您上面的答案吗?
  • @user3613025 会的,但你不需要 numpy。查看其他答案。
  • @user3613025,np.digitize 所做的只是找出值在从bins 的连续成员推导出的范围内的位置。结果是一个整数,例如5 在这种情况下。然后通过字典将 5 映射到 316.0(values 中的第 5 个值)。
【解决方案4】:

您的代码的问题在于,python 会将您字典中的键评估为 True/False。

如何创建一个映射表(即元组到值的字典):

sound_barrier = { (0, 1524): 340.3, (1524, 3048): 334.4, (3048, 4572): 328.4, ... }
def get_mapping(table, value):
    for k in table: 
        if k[0] < value < k[1]:
            return table[k]
get_mapping(sound_barrier, 2000)

【讨论】:

  • 为什么要在这里使用dict
  • 问题是将 if/else 语句转换为使用字典。诚然,这可以使用元组列表重写。
猜你喜欢
  • 2022-01-26
  • 2019-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多