我需要用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)
答案 0 :(得分: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
是一个实用函数,它返回一个可迭代的对象,它产生索引和值的元组,它可以用于松散地说,#34;迭代期间当前索引可用"。
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
答案 1 :(得分:0)
基于迭代器的解决方案
questions_missed = list(index for (index, _)
in filter(
lambda (_, (answer, solution)): answer != solution,
enumerate(zip(student_answers, exam_solution))))
对于纯粹主义者,请注意您应从zip
导入等效filter
和izip
(ifilter
和itertools
)。
答案 2 :(得分: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-arrays,可以通过==
和!=
进行元素比较。 .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的因素 - 这肯定是很多。
可能性能不会成为你的问题,不过,我认为值得指出。