Как преобразовать отображение диапазонов в словарь - PullRequest
0 голосов
/ 13 декабря 2018

Как это можно преобразовать в словарь?

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
}

Спасибо!

Ответы [ 10 ]

0 голосов
/ 15 декабря 2018

Я не математик, но подумал, что интерполяция может, возможно, сработает для этого?

    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 и убить, потому что это интерполяция , поэтому ваши интересующие точки данных должны быть в пределах выборки'способная область.

0 голосов
/ 13 декабря 2018

Без наречия вы могли бы решить проблему следующим образом:

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 предпочтительнее, чем в зависимости от конкретной детали версии.

0 голосов
/ 13 декабря 2018

Вы можете использовать словарь для хранения информации об аттестации, но это не дает никаких преимуществ, поскольку вы не можете использовать быстрый поиск по словарю с этими диапазонами.Вместо этого я бы предложил использовать отсортированный список из (points, grade) пар, а затем использовать bisect для бинарного поиска совпадений в O (logn).

>>> 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

Распаковкаgrade_ranges до points и scores здесь необязательны, но ИМХО это немного чище.Если вы не разархивируете, вам придется передать кортеж на bisect, например bisect(grade_ranges, (55,))

0 голосов
/ 13 декабря 2018

Dicts особенно полезны, если вы хотите хранить пары ключ-значение и хотите иметь возможность быстро получить произвольную запись.Как показывают другие ответы, вам нужно только пройти последовательность элементов и использовать значение первого из них, которое соответствует.Таким образом, наиболее простой (и, вероятно, наиболее эффективной) стратегией является использование типа данных последовательности.Вот как это выглядит в коде:

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

Дики хороши, но если вам не нужны их способности, используйте что-нибудь попроще.

0 голосов
/ 13 декабря 2018

Если вы можете использовать стороннюю библиотеку, вы можете использовать Панд через pd.cut.Это будет особенно эффективно, если у вас есть большое количество входных оценок для классификации.

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

См. По теме: Как отобразить числовые данные в категории / ячейки в кадре данных Pandas

0 голосов
/ 13 декабря 2018

Другой вариант - использовать range-key-dict :

from range_key_dict import RangeKeyDict

range_key_dict = RangeKeyDict({
    (96.5, 100): 5.83,
    (92.5, 96.5): 5.5,
    (89.5, 92.5): 5.16,
    (86.5, 89.5): 4.83,
    (82.5, 86.5): 4.5,
    (79.5, 82.5): 4.16,
    (76.5, 79.5): 3.83,
    (72.5, 76.5): 3.5,
    (69.5, 72.5): 3.16,
    (68.5, 69.5): 2.83,
    (64.5, 68.5): 2.5,
    (0, 64.5): 0
})

assert range_key_dict[96.5] == 5.83
assert range_key_dict[96.4] == 5.5
assert range_key_dict[96.49] == 5.5

Вы можете установить этот пакет Python с pip install range-key-dict.

Вам также потребуется проверить исходный код на сложность, так как это не будет поддерживать хеширование O (1), как в обычных словарях.

Может быть проще и эффективнее использовать обычные операторы if.

0 голосов
/ 13 декабря 2018

Если вы используете Python до 3.6, вы можете использовать collections.OrderedDict (включая 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 в порядке убывания или всегда принимаете итерируемые итерируемые элементы, а затем сортируйте их (я использую кортеж из кортежей, приведенных выше, но все в той же форме должно работать и быть легко сортируемым) В противном случае он вернет неправильные результаты.

0 голосов
/ 13 декабря 2018

Это будет один из способов, если вам действительно нужно использовать словарь;использование словарных ключей в качестве значений для проверки условий и словарных значений в качестве значений, которые должны быть возвращены.

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
0 голосов
/ 13 декабря 2018

Краткий ответ: вы должны , а не преобразовать это в словарь.Это лучше всего подходит в качестве функции, и кажется, что вы просто упускаете определение своей функции, так как я вижу, что вы используете 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
0 голосов
/ 13 декабря 2018

Невозможно преобразовать эту логику в словарь.Словари являются парами ключ-значение, поэтому вы не можете выполнить проверку «больше, чем», просто выполнив поиск.

...