등급 시스템 기능에서 반복적 인 if-elif 문을 어떻게 단순화 할 수 있습니까?


20

목표는 점수를 '0 to 1'시스템에서 'F to A'시스템으로 변환하는 프로그램을 구축하는 것입니다.

  • score >= 0.9'A'를 인쇄 하면
  • score >= 0.8'B'를 인쇄 하면
  • 0.7, C
  • 0.6, D
  • 그리고 그 지점보다 낮은 값은

이것은 그것을 빌드하는 방법이며 프로그램에서 작동하지만 다소 반복적입니다.

if scr >= 0.9:
    print('A')
elif scr >= 0.8:
    print('B')
elif scr >= 0.7:
    print('C')
elif scr >= 0.6:
    print('D')
else:
    print('F')

복합 명령문이 반복적이지 않도록 함수를 빌드하는 방법이 있는지 알고 싶습니다.

나는 완전한 초보자이지만 다음과 같은 내용이 있습니다.

def convertgrade(scr, numgrd, ltrgrd):
    if scr >= numgrd:
        return ltrgrd
    if scr < numgrd:
        return ltrgrd

가능합니까?

여기서 의도는 나중에 scr, numbergrade 및 letter grade 만 인수로 전달하여 호출 할 수 있다는 것입니다.

convertgrade(scr, 0.9, 'A')
convertgrade(scr, 0.8, 'B')
convertgrade(scr, 0.7, 'C')
convertgrade(scr, 0.6, 'D')
convertgrade(scr, 0.6, 'F')

더 적은 수의 인수를 전달할 수 있으면 더 좋습니다.



답변:


30

bisect 모듈을 사용하여 숫자 테이블 조회를 수행 할 수 있습니다 .

from bisect import bisect 

def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):
     i = bisect(breakpoints, score)
     return grades[i]

>>> [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]
['F', 'A', 'C', 'C', 'B', 'A', 'A']

2
사용에 대한 추가 +1을 원합니다 bisect. 이것은 너무 드물게 사용됩니다.
— norok2

4
@ norok2 4 가지 요소의 목록이 시작해야 할 곳이라고 생각하지 않습니다. 이러한 작은 목록의 경우 선형 스캔이 더 빠를 수 있습니다. 헤드 업없이 변경 가능한 기본 인수 사용;)
— schwobaseggl

1
물론, 그것은 문제의 학습 측면을 해치지 않고 아프지 않지만 나는 그것이 적절하다고 생각합니다.
— norok2

2
이것은 bisect 모듈의 예입니다
— dawg

작은 목록에도 불구하고 @schwobaseggl은 더 빠릅니다. 내 노트북에서 bisect 솔루션은 1.2µs, 루프는 1.5µs
— Iftah

10

이 라인을 따라 무언가를 할 수 있습니다.

# if used repeatedly, it's better to declare outside of function and reuse
# grades = list(zip('ABCD', (.9, .8, .7, .6)))

def grade(score):
    grades = zip('ABCD', (.9, .8, .7, .6))
    return next((grade for grade, limit in grades if score >= limit), 'F')

>>> grade(1)
'A'
>>> grade(0.85)
'B'
>>> grade(0.55)
'F'

이것은 next에 의해 생성 된 점수 등급 쌍에 대해 생성기의 기본 인수와 함께 사용 됩니다 zip. 루프 접근 방식과 거의 동일합니다.


5

각 등급에 임계 값을 할당 할 수 있습니다.

grades = {"A": 0.9, "B": 0.8, "C": 0.7, "D": 0.6, "E": 0.5}

def convert_grade(scr):
    for ltrgrd, numgrd in grades.items():
        if scr >= numgrd:
            return ltrgrd
    return "F"

2
Python 3.6 이하를 사용하는 경우 sorted(grades.items())dicts가 정렬되지 않을 수 있으므로 해야합니다 .
— wjandrea

모든 Python 버전에서 안정적으로 작동하지는 않습니다. dict의 순서는 보장되지 않습니다. 또한 dict중요한 순서이므로 데이터가 불필요하게 무거운 데이터 구조이며 키가 아닌 인덱스 (순서)로 찾고 있습니다.
— schwobaseggl

1
물론 가장 효율적이지는 않지만 모든 표시가 해당 임계 값에 가깝게 작성되므로 가장 읽기 쉽습니다. 차라리 dict을 쌍의 튜플로 바꾸는 것이 좋습니다.
— norok2

@schwobaseggl이 특정 작업의 경우 예, 튜플 목록이 dict보다 낫지 만이 코드가 모두 모듈에 들어가면 dict은 문자 등급-> 임계 값을 조회 할 수 있습니다.
— wjandrea

1
@wjandrea 무엇이든,와 같은 것을 허용하기 위해 키와 값을 교환해야 grades[int(score*10)/10.0]하지만 Decimal플로트는 악의적으로 악의적 인 dict 키로 사용해야 합니다.
— schwobaseggl

5

이 특정한 경우 외부 모듈이나 발전기가 필요하지 않습니다. 몇 가지 기본 수학으로 충분하고 빠릅니다!

grades = ["A", "B", "C", "D", "F"]

def convert_score(score):
    return grades[-max(int(score * 10) - 5, 0) - 1]

# Examples:
print(convert_grade(0.61)) # "D"
print(convert_grade(0.37)) # "F"
print(convert_grade(0.94)) # "A"

2

np.select여러 조건에 대해 numpy 라이브러리에서 사용할 수 있습니다 .

>> x = np.array([0.9,0.8,0.7,0.6,0.5])

>> conditions  = [ x >= 0.9,  x >= 0.8, x >= 0.7, x >= 0.6]
>> choices     = ['A','B','C','D']

>> np.select(conditions, choices, default='F')
>> array(['A', 'B', 'C', 'D', 'F'], dtype='<U1')

2

이 문제를 해결하는 간단한 아이디어가 있습니다.

def convert_grade(numgrd):
    number = min(9, int(numgrd * 10))
    number = number if number >= 6 else 4
    return chr(74 - number)

지금,

print(convert_grade(.95))  # --> A 
print(convert_grade(.9))  # --> A
print(convert_grade(.4))  # --> F
print(convert_grade(.2))  # --> F

1

를 사용 numpy.searchsorted하면 한 번의 호출로 여러 점수를 처리 할 수있는 다음과 같은 멋진 옵션을 추가로 사용할 수 있습니다 .

import numpy as np

grades = np.array(['F', 'D', 'C', 'B', 'A'])
thresholds = np.arange(0.6, 1, 0.1)

scores = np.array([0.75, 0.83, 0.34, 0.9])
grades[np.searchsorted(thresholds, scores)]  # output: ['C', 'B', 'F', 'A']

1

간단한 사례를 제공했습니다. 그러나 논리가 복잡해 지면 혼란을 처리하기 위한 규칙 엔진 이 필요할 수 있습니다 .

Sauron Rule 엔진을 사용 하거나 PYPI에서 일부 Python 규칙 엔진을 찾을 수 있습니다 .


1
>>> grade = lambda score:'FFFFFFDCBAA'[int(score*100)//10]
>>> grade(0.8)
'B'

1
이 코드는 질문에 대답 할 수 있지만 작동 방식과 사용시기를 설명하는 컨텍스트를 포함하는 것이 좋습니다. 코드 전용 답변은 장기적으로 유용하지 않습니다.
— 무스타파

0

재귀 접근법을 사용할 수도 있습니다.

grade_mapping = list(zip((0.9, 0.8, 0.7, 0.6, 0), 'ABCDF'))
def get_grade(score, index = 0):
    if score >= grade_mapping[index][0]:
        return(grade_mapping[index][1])
    else:
        return(get_grade(score, index = index + 1))

>>> print([get_grade(score) for score in [0, 0.59, 0.6, 0.69, 0.79, 0.89, 0.9, 1]])
['F', 'F', 'D', 'D', 'C', 'B', 'A', 'A']

0

보다 간결하고 이해하기 어려운 접근 방식은 다음과 같습니다.

첫 번째 솔루션은 math라이브러리 에서 바닥 기능을 사용해야 합니다.

from math import floor
def grade(mark):
    return ["D", "C", "B", "A"][min(floor(10 * mark - 6), 3)] if mark >= 0.6 else "F"

그리고 어떤 이유로 math라이브러리를 가져 오는 것이 당신을 귀찮게합니다. 바닥 기능에 대한 해결 방법을 사용할 수 있습니다.

def grade(mark):
    return ["D", "C", "B", "A"][min(int(10 * mark - 6) // 1, 3)] if mark >= 0.6 else "F"

이것들은 약간 복잡하며 진행중인 일을 이해하지 않으면 사용하지 않는 것이 좋습니다. 등급의 증분이 0.1이라는 사실을 이용하는 특정 솔루션은 0.1 이외의 증분을 사용하면이 기술을 사용하여 작동하지 않을 수 있습니다. 또한 마크를 등급에 매핑하기위한 쉬운 인터페이스가 없습니다. bisect를 사용하는 dawg와 같은 일반적인 솔루션이 더 적합하거나 schwobaseggl의 매우 깨끗한 솔루션 일 것입니다. 왜 내가이 답변을 게시하는지 잘 모르겠지만 파이썬의 다목적 성격을 보여주는 한 줄로 라이브러리가없는 문제를 해결하려는 시도 일뿐입니다 (라이브러리 사용이 나쁘다는 것을 말하려고하지는 않습니다).


0

받아쓰기를 사용할 수 있습니다.

암호

def grade(score):
    """Return a letter grade."""
    grades = {100: "A", 90: "A", 80: "B", 70: "C", 60: "D"}
    return grades.get((score // 10) * 10, "F")

데모

[grade(scr) for scr in [100, 33, 95, 61, 77, 90, 89]]

# ['A', 'F', 'A', 'D', 'C', 'A', 'B']

점수가 실제로 0과 1 사이이면 먼저 100을 곱한 다음 점수를 찾으십시오.


0

희망이 도움이되기를 바랍니다 : if scr> = 0.9 : print ( 'A') elif 0.9> scr> = 0.8 : print ( 'B') elif 0.8> scr> = 0.7 : Print ( 'C') elif 0.7 scr> = 0.6 : 인쇄 ( 'D') else : 인쇄 ( 'F')


-3

당신은 숫자의 목록을 가지고 다음에 갈 성적 목록을 가질 수 있습니다 :

scores = (0.9, 0.8, 0.7, 0.6, 0.6)
lettergrades = ("A", "B", "C", "D", "F", "F")

그런 다음 지정된 점수를 문자 등급으로 변환하려면 다음을 수행하십시오.

item = 1 # Item 1 would be 0.8
scr = lettergrades[item]

그러면 최종 점수는입니다 "B".


3
경우 당신은 DV의에 대해 궁금 :이 솔루션은 같은 점수에서 얻을 수있는 방법 제공하지 않습니다 0.83등급에를 "B". 당신은 점수에서 색인으로 얻는 방법을 보여 주어야합니다 item.
— schwobaseggl
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.