2014-04-15 35 views
1

我需要用Python编写一个程序,比较两个并行列表来评分多项选择题考试。一个清单有考试解决方案,第二个清单有一个学生的答案。每个错过的问题的问题编号将使用自然索引编号存储在第三个列表中。解决方案必须使用索引。Python列表比较问题

我不断收到为第三个列表返回的空列表。所有帮助非常感谢!

def main(): 
    exam_solution = ['B', 'D', 'A', 'A', 'C', 'A', 'B', 'A', 'C', 'D', 'B', 'C',\ 
       'D', 'A', 'D', 'C', 'C', 'B', 'D', 'A'] 
    student_answers = ['B', 'D', 'B', 'A', 'C', 'A', 'A', 'A', 'C', 'D', 'B', 'C',\ 
       'D', 'B', 'D', 'C', 'C', 'B', 'D', 'A'] 

    questions_missed = [] 

    for item in exam_solution: 
     if item not in student_answers: 
      questions_missed.append(item) 
+3

post'exam_solution'和'student_answers' –

+0

你之前的问题是因为缺少代码而被问到的。现在你已经提供了三行*的片段。请发布*所有相关的代码*。 – msvalkon

+0

你的问题是,字母A-D都在这两个列表中,所以你不'追加任何东西!你需要两两比较答案,马歇尔的答案涵盖了答案。 “解决方案必须使用索引”是线索 - 你不知道你为什么没有? – jonrsharpe

回答

5
questions_missed = [i for i, (ex,st) in enumerate(zip(exam_solution, student_answers)) if ex != st] 

或替代,如果你喜欢遍历列表解析:

questions_missed = [] 
for i, (ex,st) in enumerate(zip(exam_solution, student_answers)): 
    if ex != st: 
     questions_missed.append(i) 

两个给[2,6,13]

说明:

enumerate是一个效用函数返回一个迭代产生索引和va的元组的对象可以松散地说,“可以在迭代过程中使用当前索引”。

Zip创建一个元组列表,其中包含两个或多个可迭代对象(在您的案例列表中)的相应元素。

我宁愿列表理解版本。

如果我加入一些计时代码,我看到的性能并没有真正区别在这里:

def list_comprehension_version(): 
    questions_missed = [i for i, (ex,st) in enumerate(zip(exam_solution, student_answers)) if ex != st] 
    return questions_missed 

def loop_version(): 
    questions_missed = [] 

    for i, (ex,st) in enumerate(zip(exam_solution, student_answers)): 
     if ex != st: 
      questions_missed.append(i) 

    return questions_missed 

import timeit 

print "list comprehension:", timeit.timeit("list_comprehension_version", "from __main__ import exam_solution, student_answers, list_comprehension_version", number=10000000) 
print "loop:", timeit.timeit("loop_version", "from __main__ import exam_solution, student_answers, loop_version", number=10000000) 

给出:

list comprehension: 0.895029446804 
loop: 0.877159359719 
+0

哇......谢谢!解释也很棒。我只是在看这些。感谢您包括他们。 – user3534918

+0

不客气,我很高兴它帮助你。 –

0

基于迭代器解决方案

questions_missed = list(index for (index, _) 
         in filter(
          lambda (_, (answer, solution)): answer != solution, 
          enumerate(zip(student_answers, exam_solution)))) 

对于纯粹主义者,请注意您应该输入zip和的等价物10(izipifilter)从itertools

0

我想起了另一个解决方案。我把在一个单独的答案,因为它是“特殊”

使用numpy的这个任务可以通过以下方式实现:

import numpy as np 
exam_solution = np.array(exam_solution) 
student_answers = np.array(student_answers) 

(exam_solution!=student_answers).nonzero()[0] 

随着numpy的阵列,按元素比较通过==!=是可能的。 .nonzero()返回非零数组元素的索引。而已。

现在的时机非常有趣。为了您的19元素列表,表演(N = 19,重复= 100,000):

list comprehension: 0.904024521544 
loop: 0.936516107421 
numpy: 0.349371968612 

这已经是近3尼斯的因素,但不是惊人的。

但是当我通过100倍增加你的列表的大小,我得到(N = 19 * 100 = 1900,重复= 1000):

list comprehension: 0.866544042939 
loop: 1.04464069977 
numpy: 0.0334220694495 

现在我们有26的因素或31 - 这绝对是很多。

也许,性能不会是你的问题,但是,尽管如此,我认为值得指出。