Ответы:
Если вам нужен только один элемент, используйте count
метод:
>>> [1, 2, 3, 4, 1, 4, 1].count(1)
3
Не используйте это, если вы хотите сосчитать несколько предметов. Вызов count
в цикле требует отдельного прохода по списку для каждого count
вызова, что может иметь катастрофические последствия для производительности. Если вы хотите сосчитать все элементы или даже просто несколько элементов, используйте Counter
, как описано в других ответах.
Используйте, Counter
если вы используете Python 2.7 или 3.x, и вы хотите количество вхождений для каждого элемента:
>>> from collections import Counter
>>> z = ['blue', 'red', 'blue', 'yellow', 'blue', 'red']
>>> Counter(z)
Counter({'blue': 3, 'red': 2, 'yellow': 1})
isinstance
. Поэтому, если вы уверены в данных, с которыми работаете, может быть лучше написать пользовательскую функцию без проверки типа и экземпляра.
isinstance
звонит? Даже с миллионами строк вызов Counter
требует только одного isinstance
вызова, чтобы проверить, является ли его аргумент отображением. Скорее всего, вы неправильно оценили, что кушает все время.
Counter
были направлены на подсчет больших итераций, а не на количество итераций. Подсчет итерируемой миллионной строки будет проходить быстрее, Counter
чем при ручной реализации. Если вы хотите вызывать update
много итераций, вы можете ускорить процесс, соединив их в одну итерацию с itertools.chain
.
Подсчет вхождений одного элемента в списке
Для подсчета вхождений только одного элемента списка вы можете использовать count()
>>> l = ["a","b","b"]
>>> l.count("a")
1
>>> l.count("b")
2
Подсчет вхождений всех элементов в списке также называется «подсчетом» списка или созданием счетчика.
Подсчет всех предметов с помощью count ()
Для подсчета вхождений предметов в l
один можно просто использовать понимание списка и count()
метод
[[x,l.count(x)] for x in set(l)]
(или аналогично со словарем dict((x,l.count(x)) for x in set(l))
)
Пример:
>>> l = ["a","b","b"]
>>> [[x,l.count(x)] for x in set(l)]
[['a', 1], ['b', 2]]
>>> dict((x,l.count(x)) for x in set(l))
{'a': 1, 'b': 2}
Подсчет всех предметов с помощью счетчика ()
Кроме того, есть более быстрый Counter
класс из collections
библиотеки
Counter(l)
Пример:
>>> l = ["a","b","b"]
>>> from collections import Counter
>>> Counter(l)
Counter({'b': 2, 'a': 1})
Насколько быстрее счетчик?
Я проверил, насколько быстрее Counter
для подсчета списков. Я опробовал оба метода с несколькими значениями, n
и оказалось, что Counter
быстрее с постоянным коэффициентом примерно 2.
Вот скрипт, который я использовал:
from __future__ import print_function
import timeit
t1=timeit.Timer('Counter(l)', \
'import random;import string;from collections import Counter;n=1000;l=[random.choice(string.ascii_letters) for x in range(n)]'
)
t2=timeit.Timer('[[x,l.count(x)] for x in set(l)]',
'import random;import string;n=1000;l=[random.choice(string.ascii_letters) for x in range(n)]'
)
print("Counter(): ", t1.repeat(repeat=3,number=10000))
print("count(): ", t2.repeat(repeat=3,number=10000)
И вывод:
Counter(): [0.46062711701961234, 0.4022796869976446, 0.3974247490405105]
count(): [7.779430688009597, 7.962715800967999, 8.420845870045014]
Counter
это намного быстрее для больших списков. Метод понимания списка O (n ^ 2), Counter
должен быть O (n).
isinstance
. Поэтому, если вы уверены в данных, с которыми работаете, может быть лучше написать пользовательскую функцию без проверки типа и экземпляра.
Другой способ получить количество вхождений каждого элемента в словаре:
dict((i, a.count(i)) for i in a)
n * (number of different items)
операции, не считая время, необходимое для создания набора. Использование collections.Counter
действительно намного лучше.
i
, потому что он попытается ввести несколько ключей одинакового значения в словаре. dict((i, a.count(i)) for i in a)
list.count(x)
возвращает количество раз x
появляется в списке
видеть: http://docs.python.org/tutorial/datastructures.html#more-on-lists
Учитывая элемент, как я могу подсчитать его вхождения в списке в Python?
Вот список примеров:
>>> l = list('aaaaabbbbcccdde')
>>> l
['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'e']
list.count
Есть list.count
метод
>>> l.count('b')
4
Это прекрасно работает для любого списка. У кортежей также есть этот метод:
>>> t = tuple('aabbbffffff')
>>> t
('a', 'a', 'b', 'b', 'b', 'f', 'f', 'f', 'f', 'f', 'f')
>>> t.count('f')
6
collections.Counter
А потом есть коллекции. Счетчик. Вы можете сбросить любую итерацию в счетчик, а не просто в список, и счетчик сохранит структуру данных счетчиков элементов.
Применение:
>>> from collections import Counter
>>> c = Counter(l)
>>> c['b']
4
Счетчики основаны на словарях Python, их ключи являются элементами, поэтому ключи должны быть хэшируемыми. Они в основном похожи на наборы, которые допускают избыточные элементы в них.
collections.Counter
Вы можете добавить или вычесть с помощью итераций из вашего счетчика:
>>> c.update(list('bbb'))
>>> c['b']
7
>>> c.subtract(list('bbb'))
>>> c['b']
4
И вы можете выполнять множественные операции со счетчиком:
>>> c2 = Counter(list('aabbxyz'))
>>> c - c2 # set difference
Counter({'a': 3, 'c': 3, 'b': 2, 'd': 2, 'e': 1})
>>> c + c2 # addition of all elements
Counter({'a': 7, 'b': 6, 'c': 3, 'd': 2, 'e': 1, 'y': 1, 'x': 1, 'z': 1})
>>> c | c2 # set union
Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1, 'y': 1, 'x': 1, 'z': 1})
>>> c & c2 # set intersection
Counter({'a': 2, 'b': 2})
Другой ответ предполагает:
Почему бы не использовать панд?
Панды - это обычная библиотека, но ее нет в стандартной библиотеке. Добавление его в качестве требования нетривиально.
Для этого варианта использования есть встроенные решения как в самом объекте списка, так и в стандартной библиотеке.
Если ваш проект еще не требует панды, было бы глупо сделать это требованием только для этой функциональности.
Я сравнил все предложенные решения (и несколько новых) с perfplot ( мой небольшой проект).
Для достаточно больших массивов получается, что
numpy.sum(numpy.array(a) == 1)
немного быстрее, чем другие решения.
numpy.bincount(a)
это то, что вы хотите.
Код для воспроизведения сюжетов:
from collections import Counter
from collections import defaultdict
import numpy
import operator
import pandas
import perfplot
def counter(a):
return Counter(a)
def count(a):
return dict((i, a.count(i)) for i in set(a))
def bincount(a):
return numpy.bincount(a)
def pandas_value_counts(a):
return pandas.Series(a).value_counts()
def occur_dict(a):
d = {}
for i in a:
if i in d:
d[i] = d[i]+1
else:
d[i] = 1
return d
def count_unsorted_list_items(items):
counts = defaultdict(int)
for item in items:
counts[item] += 1
return dict(counts)
def operator_countof(a):
return dict((i, operator.countOf(a, i)) for i in set(a))
perfplot.show(
setup=lambda n: list(numpy.random.randint(0, 100, n)),
n_range=[2**k for k in range(20)],
kernels=[
counter, count, bincount, pandas_value_counts, occur_dict,
count_unsorted_list_items, operator_countof
],
equality_check=None,
logx=True,
logy=True,
)
2.
from collections import Counter
from collections import defaultdict
import numpy
import operator
import pandas
import perfplot
def counter(a):
return Counter(a)
def count(a):
return dict((i, a.count(i)) for i in set(a))
def bincount(a):
return numpy.bincount(a)
def pandas_value_counts(a):
return pandas.Series(a).value_counts()
def occur_dict(a):
d = {}
for i in a:
if i in d:
d[i] = d[i]+1
else:
d[i] = 1
return d
def count_unsorted_list_items(items):
counts = defaultdict(int)
for item in items:
counts[item] += 1
return dict(counts)
def operator_countof(a):
return dict((i, operator.countOf(a, i)) for i in set(a))
perfplot.show(
setup=lambda n: list(numpy.random.randint(0, 100, n)),
n_range=[2**k for k in range(20)],
kernels=[
counter, count, bincount, pandas_value_counts, occur_dict,
count_unsorted_list_items, operator_countof
],
equality_check=None,
logx=True,
logy=True,
)
Если вы можете использовать pandas
, то value_counts
есть для спасения.
>>> import pandas as pd
>>> a = [1, 2, 3, 4, 1, 4, 1]
>>> pd.Series(a).value_counts()
1 3
4 2
3 1
2 1
dtype: int64
Он также автоматически сортирует результат по частоте.
Если вы хотите, чтобы результат был в списке, выполните следующие действия.
>>> pd.Series(a).value_counts().reset_index().values.tolist()
[[1, 3], [4, 2], [3, 1], [2, 1]]
Почему бы не использовать панд?
import pandas as pd
l = ['a', 'b', 'c', 'd', 'a', 'd', 'a']
# converting the list to a Series and counting the values
my_count = pd.Series(l).value_counts()
my_count
Вывод:
a 3
d 2
b 1
c 1
dtype: int64
Если вы ищете отсчет определенного элемента, скажем , попробуйте:
my_count['a']
Вывод:
3
У меня была эта проблема сегодня, и я нашел собственное решение, прежде чем я решил проверить SO. Эта:
dict((i,a.count(i)) for i in a)
действительно очень медленно для больших списков. Мое решение
def occurDict(items):
d = {}
for i in items:
if i in d:
d[i] = d[i]+1
else:
d[i] = 1
return d
на самом деле немного быстрее, чем решение Counter, по крайней мере для Python 2.7.
# Python >= 2.6 (defaultdict) && < 2.7 (Counter, OrderedDict)
from collections import defaultdict
def count_unsorted_list_items(items):
"""
:param items: iterable of hashable items to count
:type items: iterable
:returns: dict of counts like Py2.7 Counter
:rtype: dict
"""
counts = defaultdict(int)
for item in items:
counts[item] += 1
return dict(counts)
# Python >= 2.2 (generators)
def count_sorted_list_items(items):
"""
:param items: sorted iterable of items to count
:type items: sorted iterable
:returns: generator of (item, count) tuples
:rtype: generator
"""
if not items:
return
elif len(items) == 1:
yield (items[0], 1)
return
prev_item = items[0]
count = 1
for item in items[1:]:
if prev_item == item:
count += 1
else:
yield (prev_item, count)
count = 1
prev_item = item
yield (item, count)
return
import unittest
class TestListCounters(unittest.TestCase):
def test_count_unsorted_list_items(self):
D = (
([], []),
([2], [(2,1)]),
([2,2], [(2,2)]),
([2,2,2,2,3,3,5,5], [(2,4), (3,2), (5,2)]),
)
for inp, exp_outp in D:
counts = count_unsorted_list_items(inp)
print inp, exp_outp, counts
self.assertEqual(counts, dict( exp_outp ))
inp, exp_outp = UNSORTED_WIN = ([2,2,4,2], [(2,3), (4,1)])
self.assertEqual(dict( exp_outp ), count_unsorted_list_items(inp) )
def test_count_sorted_list_items(self):
D = (
([], []),
([2], [(2,1)]),
([2,2], [(2,2)]),
([2,2,2,2,3,3,5,5], [(2,4), (3,2), (5,2)]),
)
for inp, exp_outp in D:
counts = list( count_sorted_list_items(inp) )
print inp, exp_outp, counts
self.assertEqual(counts, exp_outp)
inp, exp_outp = UNSORTED_FAIL = ([2,2,4,2], [(2,3), (4,1)])
self.assertEqual(exp_outp, list( count_sorted_list_items(inp) ))
# ... [(2,2), (4,1), (2,1)]
Самый быстрый использует цикл for и хранит его в Dict.
import time
from collections import Counter
def countElement(a):
g = {}
for i in a:
if i in g:
g[i] +=1
else:
g[i] =1
return g
z = [1,1,1,1,2,2,2,2,3,3,4,5,5,234,23,3,12,3,123,12,31,23,13,2,4,23,42,42,34,234,23,42,34,23,423,42,34,23,423,4,234,23,42,34,23,4,23,423,4,23,4]
#Solution 1 - Faster
st = time.monotonic()
for i in range(1000000):
b = countElement(z)
et = time.monotonic()
print(b)
print('Simple for loop and storing it in dict - Duration: {}'.format(et - st))
#Solution 2 - Fast
st = time.monotonic()
for i in range(1000000):
a = Counter(z)
et = time.monotonic()
print (a)
print('Using collections.Counter - Duration: {}'.format(et - st))
#Solution 3 - Slow
st = time.monotonic()
for i in range(1000000):
g = dict([(i, z.count(i)) for i in set(z)])
et = time.monotonic()
print(g)
print('Using list comprehension - Duration: {}'.format(et - st))
Результат
#Solution 1 - Faster
{1: 4, 2: 5, 3: 4, 4: 6, 5: 2, 234: 3, 23: 10, 12: 2, 123: 1, 31: 1, 13: 1, 42: 5, 34: 4, 423: 3}
Simple for loop and storing it in dict - Duration: 12.032000000000153
#Solution 2 - Fast
Counter({23: 10, 4: 6, 2: 5, 42: 5, 1: 4, 3: 4, 34: 4, 234: 3, 423: 3, 5: 2, 12: 2, 123: 1, 31: 1, 13: 1})
Using collections.Counter - Duration: 15.889999999999418
#Solution 3 - Slow
{1: 4, 2: 5, 3: 4, 4: 6, 5: 2, 34: 4, 423: 3, 234: 3, 42: 5, 12: 2, 13: 1, 23: 10, 123: 1, 31: 1}
Using list comprehension - Duration: 33.0
itertools.groupby()
Другая возможность получить количество всех элементов в списке может быть с помощью itertools.groupby()
.
С «дубликатами»
from itertools import groupby
L = ['a', 'a', 'a', 't', 'q', 'a', 'd', 'a', 'd', 'c'] # Input list
counts = [(i, len(list(c))) for i,c in groupby(L)] # Create value-count pairs as list of tuples
print(counts)
Возвращает
[('a', 3), ('t', 1), ('q', 1), ('a', 1), ('d', 1), ('a', 1), ('d', 1), ('c', 1)]
Обратите внимание, как он объединил первые три a
в качестве первой группы, в то время как другие группы a
присутствуют ниже по списку. Это происходит потому, что список ввода L
не был отсортирован. Иногда это может быть полезным, если группы фактически должны быть отдельными.
С уникальным количеством
Если требуется уникальное количество групп, просто отсортируйте входной список:
counts = [(i, len(list(c))) for i,c in groupby(sorted(L))]
print(counts)
Возвращает
[('a', 5), ('c', 1), ('d', 2), ('q', 1), ('t', 1)]
Примечание. Для создания уникальных подсчетов многие другие ответы предоставляют более простой и читаемый код по сравнению с groupby
решением. Но здесь показано, чтобы провести параллель с примером дублирования счета.
Было предложено использовать bincount numpy , однако он работает только для 1d массивов с неотрицательными целыми числами . Кроме того, результирующий массив может сбивать с толку (он содержит вхождения целых чисел от минимального до максимального в исходном списке и устанавливает 0 отсутствующих целых чисел).
Лучший способ сделать это с помощью numpy - использовать уникальную функцию с атрибутом return_counts
True. Он возвращает кортеж с массивом уникальных значений и массивом экземпляров каждого уникального значения.
# a = [1, 1, 0, 2, 1, 0, 3, 3]
a_uniq, counts = np.unique(a, return_counts=True) # array([0, 1, 2, 3]), array([2, 3, 1, 2]
и тогда мы можем соединить их как
dict(zip(a_uniq, counts)) # {0: 2, 1: 3, 2: 1, 3: 2}
Он также работает с другими типами данных и «2d списками», например
>>> a = [['a', 'b', 'b', 'b'], ['a', 'c', 'c', 'a']]
>>> dict(zip(*np.unique(a, return_counts=True)))
{'a': 3, 'b': 3, 'c': 2}
Хотя это очень старый вопрос, но так как я не нашел один лайнер, я сделал один.
# original numbers in list
l = [1, 2, 2, 3, 3, 3, 4]
# empty dictionary to hold pair of number and its count
d = {}
# loop through all elements and store count
[ d.update( {i:d.get(i, 0)+1} ) for i in l ]
print(d)
Вы также можете использовать countOf
метод встроенного модуля operator
.
>>> import operator
>>> operator.countOf([1, 2, 3, 4, 1, 4, 1], 1)
3
countOf
это реализовано? Как это соотносится с более очевидным list.count
(что выгодно от реализации C)? Есть ли преимущества?
Может быть не самым эффективным, требуется дополнительный проход для удаления дубликатов.
Функциональная реализация:
arr = np.array(['a','a','b','b','b','c'])
print(set(map(lambda x : (x , list(arr).count(x)) , arr)))
возвращает:
{('c', 1), ('b', 3), ('a', 2)}
или вернуть как dict
:
print(dict(map(lambda x : (x , list(arr).count(x)) , arr)))
возвращает:
{'b': 3, 'c': 1, 'a': 2}
sum([1 for elem in <yourlist> if elem==<your_value>])
Это вернет количество вхождений your_value
если вы хотите количество вхождений для конкретного элемента:
>>> from collections import Counter
>>> z = ['blue', 'red', 'blue', 'yellow', 'blue', 'red']
>>> single_occurrences = Counter(z)
>>> print(single_occurrences.get("blue"))
3
>>> print(single_occurrences.values())
dict_values([3, 2, 1])
def countfrequncyinarray(arr1):
r=len(arr1)
return {i:arr1.count(i) for i in range(1,r+1)}
arr1=[4,4,4,4]
a=countfrequncyinarray(arr1)
print(a)
l2=[1,"feto",["feto",1,["feto"]],['feto',[1,2,3,['feto']]]]
count=0
def Test(l):
global count
if len(l)==0:
return count
count=l.count("feto")
for i in l:
if type(i) is list:
count+=Test(i)
return count
print(Test(l2))
это будет рекурсивный подсчет или поиск элемента в списке, даже если он в списке списков
mylist = [1,7,7,7,3,9,9,9,7,9,10,0] print sorted(set([i for i in mylist if mylist.count(i)>2]))