Aikotohana
Aikotohana

Reputation: 3

Why doesn't my code for sorting list by frequency work?

I was trying to sort a list of number by their frequency, but when I try asserting, it didn't work.

So here is my code:

def frequency_sorting(numbers):
    return sorted(numbers,key=numbers.count,reverse=True)

And here is the assert that doesn't work

assert frequency_sorting([3, 4, 11, 13, 11, 4, 4, 7, 3]) == [4, 4, 4, 3, 3, 11, 11, 7, 13]

When I tried directly with the value the output was as follow:

[4, 4, 4, 3, 11, 11, 3, 13, 7]

I tried looking at others solution and I found the following that worked:

sorted(sorted(numbers), key=numbers.count, reverse=True)

Why does this work and not my code? What is the difference between the 2 codes? I don't understand why the first one doesn't work.

Upvotes: 0

Views: 93

Answers (2)

Harsh Sharma
Harsh Sharma

Reputation: 313

What sorted does in internally sort the list according to the key specified

so essentially sorted(numbers,key=numbers.count,reverse=True)

This is trying to not sort

numbers
>>
[3, 4, 11, 13, 11, 4, 4, 7, 3]

but actually sort

[numbers.count(x) for x in numbers]
>>[2, 3, 2, 1, 2, 3, 3, 1, 2]

where 2 corresponds to both 11 and 3, so sort doesn't care if the original value was 11 or 3 as long as this array gets sorted

[EDIT]

Hence the solution that works using sorted would be using sorted twice

sorted(sorted(numbers), key=numbers.count, reverse=True)

Upvotes: 0

Kirk Strauser
Kirk Strauser

Reputation: 30947

11 and 3 are both present twice, and your sorting function doesn't give a way to break ties. Since Python's sorting is stable, if A comes before B in the input list, and A and B have the same comparison key, A will also come before B in the output of sorted.

In your case, sorting the list before passing it to frequency_sorting orders your list numerically. And since sorting is stable, when you run that list through your frequency_sorting function, the result will still be in order.

If you want to do this more efficiently, you can use Counter to count your numbers with a O(n) algorithm. Sorting and list extension are not O(1), but they're still more efficient than running numbers.count on every number in the list.

from collections import Counter

def frequency_sorting(numbers):
    counted = Counter(sorted(numbers))

    result = []
    for number, count in counted.most_common():
        result.extend([number] * count)

    return result

assert frequency_sorting([3, 4, 11, 13, 11, 4, 4, 7, 3]) == [4, 4, 4, 3, 3, 11, 11, 7, 13]

Upvotes: 1

Related Questions