Python列表比较问题

时间:2014-04-15 09:01:21

标签: 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 个答案:

答案 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导入等效filterizipifilteritertools)。

答案 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的因素 - 这肯定是很多。

可能性能不会成为你的问题,不过,我认为值得指出。