मैं अपने ग्रेडिंग सिस्टम फ़ंक्शन में दोहराए जाने वाले if-elif कथनों को सरल कैसे कर सकता हूं?


19

लक्ष्य एक '0 से 1' प्रणाली से स्कोर को 'एफ से ए' सिस्टम में बदलने के लिए एक कार्यक्रम बनाना है:

  • अगर score >= 0.9'A' प्रिंट होगा
  • अगर score >= 0.8'बी' छपेगा
  • 0.7, सी
  • 0.6, डी
  • और उस बिंदु के नीचे कोई मान, एफ प्रिंट

यह इसे बनाने का तरीका है और यह कार्यक्रम पर काम करता है, लेकिन यह कुछ हद तक दोहरावदार है:

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

संभव है?

यहाँ आशय यह है कि बाद में हम इसे केवल तर्क, संख्या और पत्र ग्रेड को तर्क के रूप में पारित करके कह सकते हैं:

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

यदि कम तर्कों को पारित करना संभव होगा, तो यह और भी बेहतर होगा।



2
क्या इससे आपके सवाल का जवाब मिलता है? अजगर में ग्रेडिंग सिस्टम कैसे बनाएं?
रोडरनर

जवाबों:


29

आप न्यूमेरिक टेबल लुकअप करने के लिए बाइसेक्ट मॉड्यूल का उपयोग कर सकते हैं :

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चाहता हूं, जो मुझे लगता है कि इसका उपयोग बहुत कम किया गया है।
नोरोक

4
@ norok2 मुझे नहीं लगता कि 4 तत्वों की सूची हालांकि शुरू करने के लिए जगह है। ऐसी छोटी सूचियों के लिए एक लीनियर स्कैन तेजी से संभव होगा। इसके अलावा किसी भी सिर के बिना एक परस्पर डिफ़ॉल्ट तर्क का उपयोग;)
schwobaseggl

1
यकीन है, लेकिन यह चोट नहीं करता है और प्रश्न के सीखने के पहलू को देखते हुए, मुझे यह उचित लगता है।
नोरोक

2
यह बाइसेक्ट मॉड्यूल से उदाहरण है
dawg

@ schwobaseggl ऐसी छोटी सूचियों के लिए भी द्विशताब्दी तेज है। मेरे लैपटॉप पर बाइसेक्ट सॉल्यूशन 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
ध्यान दें, यदि आप पाइथन 3.6 या उससे नीचे का उपयोग कर रहे हैं, तो आपको ऐसा करना चाहिए sorted(grades.items())क्योंकि डाइट को छांटने की गारंटी नहीं है।
वेजेंड्रिया

यह सभी पायथन संस्करणों में मज़बूती से काम नहीं करेगा। ध्यान दें कि एक आदेश के आदेश की गारंटी नहीं है। यह भी एक dictअनावश्यक रूप से भारी डेटा संरचना है, क्योंकि यह वह क्रम है जो मायने रखता है, और आप किसी भी तरह से सूचकांक (आदेश) द्वारा देख रहे हैं, कुंजी द्वारा नहीं।
schwobaseggl

1
यकीन है कि सबसे कुशल नहीं है, लेकिन यह यकीनन सबसे पठनीय है क्योंकि सभी निशान उनकी दहलीज के करीब लिखे गए हैं। मैं बल्कि जोड़े के एक टपल के साथ हुकुम को बदलने का सुझाव देता हूं।
norok2

@schwobaseggl इस विशिष्ट कार्य के लिए, हाँ, टुपल्स की सूची एक तानाशाह से बेहतर होगी, लेकिन यदि यह सभी कोड एक मॉड्यूल में जा रहे थे, तो तानाशाह आपको पत्र ग्रेड -> दहलीज देखने की अनुमति देगा।
वेजेंड्रिया

1
@wjrearea यदि कुछ भी हो, grades[int(score*10)/10.0]तो आपको कुछ की अनुमति देने के लिए कुंजियों और मानों की अदला-बदली करनी होगी , लेकिन फिर आपको Decimalफ्लोट के रूप में उपयोग करना चाहिए जो कि गलत तरीके से व्यवहार किए गए प्रमुख कुंजियाँ हैं।
schwobaseggl

4

इस विशिष्ट मामले में आपको बाहरी मॉड्यूल या जनरेटर की आवश्यकता नहीं है। कुछ बुनियादी गणित पर्याप्त (और तेज) है!

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कई स्थितियों के लिए संख्यात्मक लाइब्रेरी से उपयोग कर सकते हैं:

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

आपने एक साधारण मामला प्रदान किया। हालाँकि यदि आपका तर्क अधिक जटिल हो रहा है, तो आपको एक नियम इंजन की आवश्यकता हो सकती है अराजकता को संभालने के लिए है।

आप सौरोन नियम इंजन आज़मा सकते हैं या PYPI से कुछ पायथन नियम इंजन पा सकते हैं।


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 के अलावा अन्य वेतन वृद्धि का उपयोग करना संभवतः इस तकनीक का उपयोग करके काम नहीं करेगा। यह भी ग्रेड के लिए अंक मानचित्रण के लिए एक आसान इंटरफ़ेस नहीं है। एक और अधिक सामान्य समाधान जैसे कि बिज़ेट का उपयोग करके डॉग द्वारा किया जाना शायद अधिक उपयुक्त है या स्क्वोबैसेग्ल का बहुत साफ समाधान है। मुझे वास्तव में यकीन नहीं है कि मैं इस उत्तर को क्यों पोस्ट कर रहा हूं, लेकिन यह बिना किसी पुस्तकालयों के समस्या को हल करने का एक प्रयास है (मैं यह कहना नहीं चाह रहा हूं कि पुस्तकालयों का उपयोग करना बुरा है) एक पंक्ति में अजगर की बहुमुखी प्रकृति का प्रदर्शन करता है।


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

आशा है कि निम्नलिखित मदद मिल सकती है: अगर scr> = 0.9: प्रिंट ('ए') एलिफ 0.9> स्क्रू> = 0.8: प्रिंट ('बी') एलिफ 0.8> स्क्रैच = = 0.7: प्रिंट ('सी') एलिफ 0.7 स्क्रू = = 0.6: प्रिंट ( 'डी') और: प्रिंट ( 'एफ')


-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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.