给定一个无序的值列表,比如

a = [5, 1, 2, 2, 4, 3, 1, 2, 3, 1, 1, 5, 2]

我怎样才能得到出现在列表中的每个值的频率,就像这样?

# `a` has 4 instances of `1`, 4 of `2`, 2 of `3`, 1 of `4,` 2 of `5`
b = [4, 4, 2, 1, 2] # expected output

当前回答

Python 2.7+引入了字典理解。从列表中构建字典将获得计数并去除重复项。

>>> a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
>>> d = {x:a.count(x) for x in a}
>>> d
{1: 4, 2: 4, 3: 2, 4: 1, 5: 2}
>>> a, b = d.keys(), d.values()
>>> a
[1, 2, 3, 4, 5]
>>> b
[4, 4, 2, 1, 2]

其他回答

郑重声明,一个实用的答案:

>>> L = [1,1,1,1,2,2,2,2,3,3,4,5,5]
>>> import functools
>>> >>> functools.reduce(lambda acc, e: [v+(i==e) for i, v in enumerate(acc,1)] if e<=len(acc) else acc+[0 for _ in range(e-len(acc)-1)]+[1], L, [])
[4, 4, 2, 1, 2]

如果你把0也算进去,那就更简洁了:

>>> functools.reduce(lambda acc, e: [v+(i==e) for i, v in enumerate(acc)] if e<len(acc) else acc+[0 for _ in range(e-len(acc))]+[1], L, [])
[0, 4, 4, 2, 1, 2]

一个解释:

我们从一个空的acc列表开始; 如果L的下一个元素e小于acc的大小,我们只需更新这个元素:如果acc的索引i是当前元素e,则v+(i==e)表示v+1,否则为之前的值v; 如果L的下一个元素e大于或等于acc的大小,我们必须展开acc以容纳新的1。

元素不必排序(itertools.groupby)。如果是负数,结果会很奇怪。

我找到了另一种方法,使用集合。

#ar is the list of elements
#convert ar to set to get unique elements
sock_set = set(ar)

#create dictionary of frequency of socks
sock_dict = {}

for sock in sock_set:
    sock_dict[sock] = ar.count(sock)

下面是使用itertools的另一个简洁的替代方案。Groupby也适用于无序输入:

from itertools import groupby

items = [5, 1, 1, 2, 2, 1, 1, 2, 2, 3, 4, 3, 5]

results = {value: len(list(freq)) for value, freq in groupby(sorted(items))}

结果

format: {value: num_of_occurencies}
{1: 4, 2: 4, 3: 2, 4: 1, 5: 2}
str1='the cat sat on the hat hat'
list1=str1.split();
list2=str1.split();

count=0;
m=[];

for i in range(len(list1)):
    t=list1.pop(0);
    print t
    for j in range(len(list2)):
        if(t==list2[j]):
            count=count+1;
            print count
    m.append(count)
    print m
    count=0;
#print m
num=[3,2,3,5,5,3,7,6,4,6,7,2]
print ('\nelements are:\t',num)
count_dict={}
for elements in num:
    count_dict[elements]=num.count(elements)
print ('\nfrequency:\t',count_dict)