2012-03-15 4 views
19

Tôi có một danh sách có số điểm học sinh có.Chuyển đổi các số thành các cấp trong danh sách python

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

Tôi muốn học sinh lớp theo đối với nhãn hiệu:

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

tôi có thể làm điều này với iterating vòng hoặc tôi có thể tìm thấy tất cả các danh sách sử dụng lambda. ví dụ:

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

Nhưng, trong các bộ lọc, tôi có thể làm việc với chỉ có một chức năng tại một thời điểm (ví dụ: dấu lớn hơn 50). Có cách nào tôi có thể sử dụng bộ lọc và lambda và nhận được kết quả cần thiết trong một dòng? Mong đợi đầu ra dưới dạng điểm với điểm. (ví dụ: 50 - A, 62 - A, 76 - A ++ ...)

Trả lời

21

Xác định một chức năng mà phải mất một dấu ấn và trả về một đại diện có thể đọc được con người, bạn có thể sử dụng larsmans's expression hoặc cái này:

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

Sử dụng string.format để định dạng từng mục nhập và bản đồ để lặp qua tất cả các mục nhập đó:

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

Danh sách kết quả hiện chứa chuỗi ở định dạng mong muốn.

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

Làm thế nào để {0} và {1 } công việc? – Josh

+0

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

15

Quên lambda, quên filter; sau đây phân loại trong một biểu thức, giả sử có một điểm B giữa A và "thất bại".

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

Bạn có thể zip kết quả của điều này với s để có được nhãn hiệu và lớp trong một danh sách.

+0

Hoặc bạn có thể sử dụng bản đồ, 'bản đồ (lambda x: (x, ' F 'if x <40 else' A ++ 'nếu x> 70 khác' A '), s) '. Hoặc chỉ mất '(x,' (và ')' tất nhiên) nếu bạn muốn chỉ điểm. Danh sách được sắp xếp để bạn có thể kết hợp nó sau này. – rplnt

+0

Bạn hiểu là 78 ​​ký tự. Bạn có được ngắt dòng miễn phí trong họ. Tôi biết nó đi ngược lại các quy tắc kiểu Google Python, nhưng tôi thích chia chúng hơn nhiều dòng, có thể ở cuối mỗi 'else'. – Droogans

+0

@Droogans: Tôi không biết các quy tắc về phong cách của Google, nhưng trong một chương trình thực tế, tôi thực sự sẽ đặt một số dấu ngắt dòng. Http://stackoverflow.com/a/5809080/166749 –

1

Bạn có thể viết bộ lọc giống như của riêng chức năng của bạn:

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

Câu trả lời hiện đang tìm kiếm như sau:

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

Sử dụng x.items() để làm bộ lọc, ví dụ

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

kết quả là

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

2 phạm vi trên một dòng có tên 'x' khác. Không khác với câu trả lời khác, vì vậy nếu bạn có đặc quyền chỉnh sửa, bản chỉnh sửa có thể phù hợp hơn câu trả lời. –