Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
150 views
in Technique[技术] by (71.8m points)

python - Using list.count to sort a list in-place using .sort() does not work. Why?

I am trying to sort a list by frequency of its elements.

>>> a = [5, 5, 4, 4, 4, 1, 2, 2]
>>> a.sort(key = a.count)
>>> a
[5, 5, 4, 4, 4, 1, 2, 2]

a is unchanged. However:

>>> sorted(a, key = a.count)
[1, 5, 5, 2, 2, 4, 4, 4]

Why does this method not work for .sort()?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

What you see is the result of a certain CPython implementation detail of list.sort. Try this again, but create a copy of a first:

a.sort(key=a.copy().count)
a
# [1, 5, 5, 2, 2, 4, 4, 4]

.sort modifies a internally, so a.count is going to produce un-predictable results. This is documented as an implementation detail.

What copy call does is it creates a copy of a and uses that list's count method as the key. You can see what happens with some debug statements:

def count(x):
    print(a)
    return a.count(x)

a.sort(key=count)
[]
[]
[]
...

a turns up as an empty list when accessed inside .sort, and [].count(anything) will be 0. This explains why the output is the same as the input - the predicates are all the same (0).

OTOH, sorted creates a new list, so it doesn't have this problem.


If you really want to sort by frequency counts, the idiomatic method is to use a Counter:

from collections import Counter

a.sort(key=Counter(a).get)
a
# [1, 5, 5, 2, 2, 4, 4, 4]

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...