Reputation: 8528
I have a list of integers(or could be even strings), which I would like to sort by the frequency of occurrences in Python, for instance:
a = [1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5]
Here the element 5
appears 4 times in the list, 4
appears 3 times. So the output sorted list would be :
result = [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
I tried using a.count()
, but it gives the number of occurrence of the element.
I would like to sort it. Any idea how to do it ?
Thanks
Upvotes: 23
Views: 43754
Reputation: 11
Don't have enough reputation to comment, so posting instead. In Python 3.10.12 doing
from collections import Counter
a = [1, 0, 1, 0]
s = sorted(a, key=Counter(a).get, reverse=True)
print(Counter(a).most_common())
print(a)
print(s)
gives
[(1, 2), (0, 2)]
[1, 0, 1, 0]
[1, 0, 1, 0]
So using sorted/sort might not give the expected results (I would have expected [0,0,1,1]
or [1,1,0,0]
). You might want to use another method of sorting for this use case. Doing
from collections import Counter
a = [1, 0, 1, 0]
d = [item for items, c in Counter(a).most_common() for item in [items] * c]
print(a)
print(d)
gives
[1, 0, 1, 0]
[1, 1, 0, 0]
You might need to sort again if the ordering of the sorted list is important.
Upvotes: 1
Reputation: 439
Dart Solution
String sortedString = '';
Map map = {};
for (int i = 0; i < s.length; i++) {
map[s[i]] = (map[s[i]] ?? 0) + 1;
// OR
// map.containsKey(s[i])
// ? map.update(s[i], (value) => ++value)
// : map.addAll({s[i]: 1});
}
var sortedByValueMap = Map.fromEntries(
map.entries.toList()..sort((e1, e2) => e1.value.compareTo(e2.value)));
sortedByValueMap.forEach((key, value) {
sortedString += key * value;
});
return sortedString.split('').reversed. Join();
Upvotes: 0
Reputation: 21
Occurrence in array and within a sets of equal size:
rev=True
arr = [6, 6, 5, 2, 9, 2, 5, 9, 2, 5, 6, 5, 4, 6, 9, 1, 2, 3, 4, 7 ,8 ,8, 8, 2]
print arr
arr.sort(reverse=rev)
ARR = {}
for n in arr:
if n not in ARR:
ARR[n] = 0
ARR[n] += 1
arr=[]
for k,v in sorted(ARR.iteritems(), key=lambda (k,v): (v,k), reverse=rev):
arr.extend([k]*v)
print arr
[6, 6, 5, 2, 9, 2, 5, 9, 2, 5, 6, 5, 4, 6, 9, 1, 2, 3, 4, 7, 8, 8, 8, 2]
[2, 2, 2, 2, 2, 6, 6, 6, 6, 5, 5, 5, 5, 9, 9, 9, 8, 8, 8, 4, 4, 7, 3, 1]
Upvotes: 0
Reputation: 114811
If you happen to be using numpy already, or if using it is an option, here's another alternative:
In [309]: import numpy as np
In [310]: a = [1, 2, 3, 3, 1, 3, 5, 4, 4, 4, 5, 5, 5]
In [311]: vals, counts = np.unique(a, return_counts=True)
In [312]: order = np.argsort(counts)[::-1]
In [313]: np.repeat(vals[order], counts[order])
Out[313]: array([5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 1, 1, 2])
That result is a numpy array. If you want to end up with a Python list, call the array's tolist()
method:
In [314]: np.repeat(vals[order], counts[order]).tolist()
Out[314]: [5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 1, 1, 2]
Upvotes: 1
Reputation: 4501
Not interesting way...
a = [1,1,2,3,3,3,4,4,4,5,5,5,5]
from collections import Counter
result = []
for v, times in sorted(Counter(a).iteritems(), key=lambda x: x[1], reverse=True):
result += [v] * times
One liner:
reduce(lambda a, b: a + [b[0]] * b[1], sorted(Counter(a).iteritems(), key=lambda x: x[1], reverse=True), [])
Upvotes: 0
Reputation: 113915
In [15]: a = [1,1,2,3,3,3,4,4,4,5,5,5,5]
In [16]: counts = collections.Counter(a)
In [17]: list(itertools.chain.from_iterable([[k for _ in range(counts[k])] for k in sorted(counts, key=counts.__getitem__, reverse=True)]))
Out[17]: [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
Alternatively:
answer = []
for k in sorted(counts, key=counts.__getitem__, reverse=True):
answer.extend([k for _ in range(counts[k])])
Of course, [k for _ in range(counts[k])]
can be replaced with [k]*counts[k]
.
So line 17 becomes
list(itertools.chain.from_iterable([[k]*counts[k] for k in sorted(counts, key=counts.__getitem__, reverse=True)]))
Upvotes: 3
Reputation: 239453
from collections import Counter
print [item for items, c in Counter(a).most_common() for item in [items] * c]
# [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
Or even better (efficient) implementation
from collections import Counter
from itertools import repeat, chain
print list(chain.from_iterable(repeat(i, c) for i,c in Counter(a).most_common()))
# [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
Or
from collections import Counter
print sorted(a, key=Counter(a).get, reverse=True)
# [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
If you prefer in-place sort
a.sort(key=Counter(a).get, reverse=True)
Upvotes: 43
Reputation: 12243
Using Python 3.3 and the built in sorted function, with the count as the key:
>>> a = [1,1,2,3,3,3,4,4,4,5,5,5,5]
>>> sorted(a,key=a.count)
[2, 1, 1, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5]
>>> sorted(a,key=a.count,reverse=True)
[5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
Upvotes: 10