Python 如何将范围映射转换为字典

Python 如何将范围映射转换为字典,python,dictionary,categorical-data,Python,Dictionary,Categorical Data,如何将其转换为词典 if grade>=96.5:return 5.83 elif grade>=92.5:return 5.5 elif grade>=89.5:return 5.16 elif grade>=86.5:return 4.83 elif grade>=82.5:return 4.5 elif grade>=79.5:return 4.16 elif grade>=76.5:return 3.83 elif grade>=72.5:

如何将其转换为词典

if grade>=96.5:return 5.83
elif grade>=92.5:return 5.5
elif grade>=89.5:return 5.16
elif grade>=86.5:return 4.83
elif grade>=82.5:return 4.5
elif grade>=79.5:return 4.16
elif grade>=76.5:return 3.83
elif grade>=72.5:return 3.5
elif grade>=69.5:return 3.16
elif grade>=68.5:return 2.83
elif grade>=64.5:return 2.5
else:return 0
我知道如何制作基本字典,但我不确定它是否会像这样:

grade_checker = {
    grade>96.5:5.83
}

谢谢

无法将此逻辑转换为字典。字典是键-值对,因此无法仅通过查找来执行“大于”检查。

简而言之,您应该而不是将其转换为字典。这是最适合作为函数的,而且您似乎缺少函数定义,因为我看到您在代码中使用了
return
。字典是从键值对构造的,因为您的条件涉及
=
求值,所以字典是不合适的。请参见下面的功能实现:

def grade_checker(grade):

    if grade>=96.5: return 5.83
    elif grade>=92.5: return 5.5
    elif grade>=89.5: return 5.16
    elif grade>=86.5: return 4.83
    elif grade>=82.5: return 4.5
    elif grade>=79.5: return 4.16
    elif grade>=76.5: return 3.83
    elif grade>=72.5: return 3.5
    elif grade>=69.5: return 3.16
    elif grade>=68.5: return 2.83
    elif grade>=64.5: return 2.5
    else: return 0

grade_checker(75)
grade_checker(62)
grade_checker(94)
返回:

3.5
0
5.5

如果你真的需要使用字典,这将是一种方法;以字典键作为条件检查值,以字典值作为返回值

grade_checker = {
    96.5: 5.83,
    92.5: 5.5,
    89.5: 5.16,
    86.5: 4.83,
    82.5: 4.5,
    79.5: 4.16,
    76.5: 3.83,
    72.5: 3.5,
    69.5: 3.16,
    68.5: 2.83,
    64.5: 2.5
}

def check_grade(grade):
    for k in grade_checker:
        if grade >= k:
            return grade_checker[k]
    return 0
检查

>>> check_grade(45.5)
0
>>> check_grade(65.5)
2.5
>>> check_grade(95)
5.5

如果您使用的是Python 3.6之前的版本,那么您可以使用(包括Python 2.7),否则
dict
对象是本机插入排序的()

这样,您就可以在
dict
上迭代并返回第一个范围匹配

# python 3.6+
grade_table = {
    96.5: 5.83,
    ...
    64.5: 2.5,
}

# pre-3.6
from collections import OrderedDict
grade_table = OrderedDict((  # this is a tuple of tuples
    (96.5, 5.83),
    ...
    (64.5, 2.5),
))

def fn(student_grade):
    for grade, value in grade_table.iteritems():
        if student_grade >= grade:
            return value

    return 0  # default
注意:如果您希望表发生更改,那么测试dict是否按降序排列,或者始终接受iterable的iterable,然后对其进行排序可能是有意义的(我使用上面的元组元组,但任何相同形式的元组都应该工作,并且易于排序),否则它将返回不正确的结果。

另一个选项是使用:

您可以使用
pip install range key dict
安装此Python包

您还需要检查源代码的复杂性,因为这不会像常规字典那样维护O(1)哈希


只使用常规if语句可能更容易、更有效

如果您希望存储键值对,并且希望能够快速检索任意条目,dict尤其有用。正如其他答案所示,您只需要遍历元素序列并使用匹配的第一个元素的值。因此,最直接(可能也是最有效)的策略是使用序列数据类型。下面是代码中的情况:

pairs = (
    (96.5, 5.83),
    (92.5, 5.5),
    (89.5, 5.16),
    (86.5, 4.83),
    (82.5, 4.5),
    (79.5, 4.16),
    (76.5, 3.83),
    (72.5, 3.5),
    (69.5, 3.16),
    (68.5, 2.83),
    (64.5, 2.5),
)

def get_grade(g):
    for grade, value in pairs:
            if g >= grade:
                return value
    return 0

Dicts很好,但是如果你不需要它们的功能,可以使用更简单的功能。

如果你可以使用第三方库,你可以通过使用Pandas。如果你有大量的输入等级要分类,这将特别有效

import pandas as pd

grade_checker = {96.5: 5.83,
                 ...,
                 64.5: 2.5}

keys, values = zip(*sorted(grade_checker.items()))
keys += (float('inf'),)  # need to add upper boundary for pd.cut input

grade = 65.5
res = pd.cut([grade], keys, labels=values).astype(float)[0]  # 2.5

请参阅相关内容:

如果没有dict,您可以这样解决问题:

import numpy as np
GRADES = np.array(
    [[96.5 , 92.5 , 89.5 , 86.5 , 82.5 , 79.5 , 76.5 , 72.5 , 69.5 , 68.5 , 64.5 ],
     [ 5.83,  5.5 ,  5.16,  4.83,  4.5 ,  4.16,  3.83,  3.5 ,  3.16, 2.83,  2.5 ]])
def get_grade(grade):
    try:
        return GRADES[1][grade > [GRADES[0]][0]
    except:
        return 0
这比字典更可取,因为内置字典仅为>=Python 3.6提供有序性保证(即,它们将按照插入键/值的顺序进行迭代)。能够在更多的Python版本上运行代码比依赖于特定的版本详细信息更可取。

您可以使用字典保存分级信息,但它并不能真正提供任何好处,因为您无法对这些范围使用快速字典查找。相反,我建议使用排序后的
(分数、等级)
对列表,然后使用二进制搜索O(logn)中的匹配分数


grade\u范围
解压到
分数
在这里是可选的,但我认为这样会更干净一些。如果你不解压,你将不得不把一个元组传递给对分,例如,对分(等级范围,(55,)

我不是一个数学爱好者,但我认为插值也许能解决这个问题

    from numpy import interp

    ak = [k for k in gc.keys()]
    av = [v for v in gc.values()]

    # np.interp needs values from lowest to highest
    ak.reverse()
    av.reverse()

    interp(79, ak, av)
    >>> 4.105

    interp(96, ak, av)
    >>> 5.78875

    interp(64, ak, av)
    >>> 2.5

您需要增加到100并减少,因为它是插值,所以您感兴趣的数据点需要在可采样范围内。

不确定为什么您需要在此处使用字典,函数仍然最适合于此。这不是有效的python语法,return只能在函数内部使用。如果这是函数的一部分,您应该包含所有代码。您使用的是什么版本的Python?有一种方法,但它仍然很难看。例如,您可以执行
d={(0,10):0}
然后执行
下一步(v代表k,v代表d.items(),如果值在范围(*k))
在这种情况下,字典实际上只是一个键值对序列,在这种情况下,您可以将其存储为一个对象序列,其中封装了下限、上限和映射的结果。事实上,我认为这样做不太安全,因为你需要证明边界没有重叠——与原始的if,then,else序列重叠边界是不可能的。我同意dict不是正确的方法,但是像你这样编写函数似乎非常冗长和重复。等级值对应按顺序存储,函数应在这些对上循环,直到找到第一个匹配项。完全同意您的意见,只是想为OP提供一个解决方案,对其原始代码进行最小更改(因为他们可能是初学者)。仅适用于Python的较新版本,并考虑插入顺序。对于其他版本,您可以只使用元组列表而不是dict,或者迭代反向排序键,或者使用
collections.orderedict
>>> import bisect
>>> grade_ranges = [(0, 0), (64.5, 2.5), (68.5, 2.83), (69.5, 3.16), 
...                 (72.5, 3.5), (76.5, 3.83), (79.5, 4.16), (82.5, 4.5), 
...                 (86.5, 4.83), (89.5, 5.16), (92.5, 5.5), (96.5, 5.83)]
...
>>> points, grade = zip(*grade_ranges)
>>> grade[bisect.bisect(points, 96.5)-1]
5.83
>>> grade[bisect.bisect(points, 73)-1]
3.5
>>> grade[bisect.bisect(points, 30)-1]
0
    from numpy import interp

    ak = [k for k in gc.keys()]
    av = [v for v in gc.values()]

    # np.interp needs values from lowest to highest
    ak.reverse()
    av.reverse()

    interp(79, ak, av)
    >>> 4.105

    interp(96, ak, av)
    >>> 5.78875

    interp(64, ak, av)
    >>> 2.5