2012-03-15 20 views
19

Mam listę, która ma liczbę znaków, które uczniowie mają.Konwersja liczb do ocen na liście Pythona

s = [50,62,15,76,57,97,82,99,45,23] 

Chcę uczniów klas według znaków:

<40 - Fail 
>50 - A Grade 
>75 - A++ Grade 

mogę to zrobić z iteracji pętli lub mogę znaleźć wszelkie listy przy użyciu lambda. na przykład:

>>> filter(lambda x:x>=50, s) 
[50, 62, 76, 57, 97, 82, 99] 

Ale w filtrze, mogę pracować tylko jedna funkcja w czasie (na przykład: znaki większe niż 50). Czy jest sposób, w jaki mogę użyć filtra i lambda i uzyskać wymagany wynik w jednym wierszu? Oczekiwany wynik jako oceny z oceną. (np. 50 - A, 62 - A, 76 - A ++ ...)

Odpowiedz

21

zdefiniować funkcję, która pobiera znak i zwracającą czytelnej reprezentacji, można użyć larsmans's expression czy to jedno:

def grade(i): 
    if i<40: return "Fail" 
    if i>75: return "A++" 
    if i>50: return "A" 

Zastosowanie do String.Format sformatuj każdy wpis i odwzoruj na iterację na wszystkie:

li = map(lambda x: "{0} - {1}".format(x, grade(x)), s) 

Wynikowa lista zawiera teraz ciągi w wybranym formacie.

for i in li: print i 

# output 

50 - None 
62 - A 
15 - Fail 
76 - A++ 
57 - A 
97 - A++ 
82 - A++ 
99 - A++ 
45 - None 
23 - Fail 
+0

W jaki sposób {0} i {1 } działa? – Josh

+0

@Josh http://docs.python.org/2/library/stdtypes.html#str.format – Anentropic

15

Zapomnij o lambda, zapomnij o filter; poniższe oceny są wyrażane w jednym wyrażeniu, przy założeniu, że istnieje klasa B między A a "niepowodzeniem".

["fail" if g < 40 else "B" if g < 60 else "A" if g < 75 else "A++" for g in s] 

Można zip wynikiem tego ze s uzyskać znaki i stopnie w jednej liście.

+0

Albo można użyć mapy, 'mapy (lambda x: (x, ' F 'if x <40 else' A ++ 'if x> 70 else' A '), s) '. Lub po prostu przegraj '(x,' (i ')' oczywiście), jeśli chcesz tylko oceny. Lista jest uporządkowana, dzięki czemu można ją później dopasować. – rplnt

+0

Rozumiemy, że ma 78 znaków. Dostajesz w nich darmowe podziały linii. Wiem, że jest to niezgodne z zasadami Google Python, ale wolę je rozbijać na wiele linii, prawdopodobnie na końcu każdego "else". – Droogans

+0

@Droogans: Nie znam reguł w stylu Google, ale w praktycznym programie rzeczywiście wprowadziłbym kilka linii. Http://stackoverflow.com/a/5809080/166749 –

1

Możesz napisać własny filtr podobny funkcję:

def filter_n(n, f, lst): 
    result = tuple([[] for i in range(n)]) 
    for elem in lst: 
     result[f(elem)].append(elem) 
    return result 

Odpowiedź jest teraz patrząc w następujący sposób:

grades = filter_n(3, lambda x: (x < 40) * 0 + 
           (60 < x <= 75) * 1 + 
           (75 < x) * 2, s) 
2
s = [50,62,15,76,57,97,82,99,45,23] 
x = dict([(a, 'A++' if a>75 else 'A' if a>55 else 'F') for a in s]) 

print x 

{97: 'A++', 45: 'F', 99: 'A++', 76: 'A++', 82: 'A++', 15: 'F', 50: 'F', 23: 'F', 57: 'A', 62: 'A'} 

Zastosowanie x.items() zrobić filtr, na przykład

filter(lambda x: x[1] == 'A', x.items()) 

wynik jest

[(57, 'A'), (62, 'A')] 
+0

2 zakresy w jednej linii, gdzie nazwa "x" to coś innego. Nie różni się zbytnio od innych odpowiedzi, więc jeśli miałeś uprawnienie do edycji, zmiana mogła być lepiej dopasowana niż odpowiedź. –

Powiązane problemy