3

I will give the specific case and the generic case so we can help more people:

I have a list of ordered lists and another list with the same length as each ordered list. Each list in the list of lists is students' answers from a large-scale evaluation, and the second is the correct answers from the test. I need to check the % of right answers, AKA how many matches are between each item in each of the lists in order. The output should be a list where 1 means there is a match, and 0 there is no match.

Example:

list1 = [['A', 'B', 'C', 'A'], ['A', 'C', 'C', 'B']]
list2 = ['A', 'B', 'C', 'A']
result = [[1, 1, 1, 1],[1, 0, 1, 0]

Thank you!

3 Answers3

2

You can use a nested list comprehension, like the following

results = [[int(value == list2[index]) for index, value in enumerate(i)] for i in list1]

This iterates over each element of list1, iterating over each element, and checking if its corresponding pair in list2 is the same.

enumerate is used to avoid range(len(list1)), which is not recommended for stylistic reasons. Equality == returns a boolean, and we cast this to an int via int, which turns True into 1 and False into 0.

Output:

>>> list1 = [['A', 'B', 'C', 'A'], ['A', 'C', 'C', 'B']]
>>> list2 = ['A', 'B', 'C', 'A']
>>> results = [[int(value == list2[index]) for index, value in enumerate(i)] for i in list1]
>>> print(results)
[[1, 1, 1, 1], [1, 0, 1, 0]]

Happy coding!

iteratedwalls
  • 223
  • 1
  • 9
2

The others have done a fine job detailing how this can be done with list comprehensions. The following code is a beginner-friendly way of getting the same answer.

final = []

# Begin looping through each list within list1
for test in list1:

    # Create a list to store each students scores within
    student = []
    for student_ans, correct_ans in zip(test, list2):

        # if student_ans == correct_ans at the same index...
        if student_ans == correct_ans:
            student.append(1)
        else:
            student.append(0)
    
    # Append the student list to the final list
    final.append(student)
Jackie
  • 198
  • 12
1

If you want to write it as a one-liner using list comprehensions

output = [[int(answer_given == correct_answer) for answer_given, correct_answer in zip(student, list2)] for student in list1]
bitflip
  • 3,436
  • 1
  • 3
  • 22
  • 2
    While a stylistic choice, `int(condition)` is often preferred over using a ternary conditional of the form `1 if condition else 0`, for brevity. This answer could also benefit from an explanation for future users. By the way, nice trick with `zip`, I'll be using that! – iteratedwalls Sep 22 '22 at 21:43
  • @iteratedwalls or really, just `answer_given == correct_answer` would do, since `True == 1` and `False == 0`, since `issubclass(bool, int)` – juanpa.arrivillaga Sep 22 '22 at 21:45
  • 1
    thanks for your feedback, I've changed it to int(answer_given == correct_answer). Just using answer_given == correct_answer returns True and False which is not what OP asked for. – bitflip Sep 22 '22 at 21:49
  • Note that just like in Javascript, if you prepend a boolean variable with `+`, it will be implicitly converted to an integer. However, it may look like a typo to the uninitiated – smac89 Sep 23 '22 at 02:34