Multi-Dimensional List Sorting [multi-column]

The following code prints the student number and the students score.

def main():
    answers = [
        ['A', 'B', 'A', 'C', 'C', 'D', 'E', 'E', 'A', 'D'],
        ['D', 'B', 'A', 'B', 'C', 'A', 'E', 'E', 'A', 'D'],
        ['E', 'D', 'D', 'A', 'C', 'B', 'E', 'E', 'A', 'D'],
        ['C', 'B', 'A', 'E', 'D', 'C', 'E', 'E', 'A', 'D'],
        ['A', 'B', 'D', 'C', 'C', 'D', 'E', 'E', 'A', 'D'],
        ['B', 'B', 'E', 'C', 'C', 'D', 'E', 'E', 'A', 'D'],
        ['B', 'B', 'A', 'C', 'C', 'D', 'E', 'E', 'A', 'D'],
        ['E', 'B', 'E', 'C', 'C', 'D', 'E', 'E', 'A', 'D']]

    keys = ['D', 'B', 'D', 'C', 'C', 'D', 'A', 'E', 'A', 'D']

    for i in range(len(answers)):
        correctCount = 0
        for j in range(len(answers[i])):
            if answers[i][j] == keys[j]:
                correctCount += 1


        results = [i,correctCount]
        print(results, end = "") # this line used to be - print("Student", i, "'s correct count is", correctCount)


main()

My goal is to sort the students scores from lowest to highest without mixing up the student number that's associated with that score. I have attempted to use the sort function in these forms:

results1 = sorted(results, key = lambda x: x[1])
results.sort(key = itemgetter(1))
results.sort()

Using all three of these attempts I still am unable to make it work. Any ideas?

Expected Output:

[3, 4]
[2, 5]
[1, 6]
[0, 7]
[5, 7]
[6, 7]
[7, 7]
[4, 8]

First Column is the Student #, second column is the score.

Upvotes: 0

Views: 72

Answers (1)

AChampion
AChampion

Reputation: 30258

You aren't constructing a list of results, results = [i, correctCount] just overwrites the results, you need:

results = []
for i in range(len(answers)):
    correctCount = 0
    for j in range(len(answers[i])):
        if answers[i][j] == keys[j]:
            correctCount += 1
    results.append([i, correctCount])
results = sorted(results, key=lambda x: x[1])

Then your sorting code should work.

However, more idiomatically in python is iterating over the actual list vs. the range(len(list)), which can generally simplify your code, the above can be rewritten:

results = []
for student, student_answers in enumerate(answers):
    correctCount = 0
    for answer, key in zip(student_answers, keys):
        if answer == key:
            correctCount += 1
    results.append([student, correctCount])
results = sorted(results, key=lambda x: x[1])

Which is more readable than the original code.
You can also reduce it with the use of comprehensions and generators:

results = []
for student, student_answers in enumerate(answers):
    results.append([student, sum(ans == key for ans, key in zip(student_answers, keys)])
results = sorted(results, key=lambda x: x[1])

And if you really want to go this far you could do the whole thing in one go:

results = sorted(((student, sum(a == k for a, k in zip(ans, keys)))
                  for student, ans in enumerate(answers)), key=lambda x: x[1])
# [(3, 4), (2, 5), (1, 6), (0, 7), (5, 7), (6, 7), (7, 7), (4, 8)]

Upvotes: 1

Related Questions