ฉันจะนับการเกิดขึ้นของรายการได้อย่างไร


1530

ให้รายการฉันจะนับเหตุการณ์ที่เกิดขึ้นในรายการใน Python ได้อย่างไร

คำตอบ:


1853

หากคุณต้องการเพียงหนึ่งรายการนับใช้countวิธีการ:

>>> [1, 2, 3, 4, 1, 4, 1].count(1)
3

อย่าใช้สิ่งนี้หากคุณต้องการนับหลายรายการ การโทรcountแบบวนซ้ำต้องผ่านรายการแยกต่างหากสำหรับการcountโทรทุกครั้งซึ่งอาจเป็นผลร้ายต่อประสิทธิภาพการทำงาน หากคุณต้องการนับรายการทั้งหมดหรือแม้กระทั่งหลายรายการให้ใช้Counterตามที่อธิบายไว้ในคำตอบอื่น ๆ


6
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]))
cpp-coder

1745

ใช้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})

2
ฉันได้พบว่าเมื่อใช้เป็นจำนวนมากนี้ (พูดคุยเกี่ยวกับล้านของสตริง) isinstanceว่ามันจะช้ามากเพราะการเรียกไปยัง ดังนั้นหากคุณแน่ใจเกี่ยวกับข้อมูลที่คุณกำลังทำงานอยู่อาจเป็นการดีกว่าที่จะเขียนฟังก์ชันที่กำหนดเองโดยไม่ต้องตรวจสอบประเภทและอินสแตนซ์
Bram Vanroy

2
@BramVanroy: isinstanceสายอะไร แม้จะมีสตริงนับล้านการโทรCounterจะต้องมีเพียงแค่การisinstanceโทรเดียวเพื่อตรวจสอบว่าอาร์กิวเมนต์เป็นการแมปหรือไม่ คุณมักจะตัดสินว่ามีอะไรที่กินอยู่ตลอดเวลา
user2357112 รองรับ Monica

คุณตีความสิ่งที่ฉันหมายถึง: ตัวนับตรวจสอบประเภทข้อมูลของคุณก่อนที่จะสร้างตัวนับ การดำเนินการนี้ใช้เวลาค่อนข้างนานและหากคุณทราบประเภทข้อมูลล่วงหน้า หากคุณดูวิธีการอัปเดตของ Counter คุณจะเห็นว่าต้องใช้ if-statement สามอย่างก่อนที่จะทำอะไรสักอย่าง หากคุณเรียกการอัปเดตบ่อยครั้งสิ่งนี้จะเพิ่มขึ้นอย่างรวดเร็ว เมื่อคุณมีการควบคุมข้อมูลของคุณและคุณรู้ว่าการป้อนข้อมูลจะเป็น iterable แน่นอนจากนั้นคุณสามารถข้ามการตรวจสอบสองครั้งแรก อย่างที่ฉันพูดฉันเพิ่งสังเกตสิ่งนี้เมื่อทำงานกับการอัปเดตหลายล้านครั้งดังนั้นจึงเป็นกรณีที่ล้ำสมัย
Bram Vanroy

2
@BramVanroy: หากคุณทำการอัปเดตหลายล้านรายการแทนที่จะเป็นเพียงแค่การนับสตริงนับล้านนั่นเป็นเรื่องที่แตกต่าง ความพยายามในการปรับCounterให้เหมาะสมในการนับ iterables ขนาดใหญ่แทนที่จะนับ iterables จำนวนมาก การนับ iterable ล้านสตริงจะเร็วขึ้นCounterกว่าด้วยการใช้งานด้วยตนเอง หากคุณต้องการที่จะเรียกupdateกับ iterables หลายท่านอาจจะไม่สามารถไปสู่สิ่งที่ความเร็วขึ้นโดยการเข้าร่วมพวกเขาเป็นหนึ่ง iterable itertools.chainกับ
user2357112 รองรับ Monica

262

การนับการเกิดขึ้นของหนึ่งรายการในรายการ

สำหรับการนับการเกิดขึ้นของรายการเดียวที่คุณสามารถใช้ count()

>>> l = ["a","b","b"]
>>> l.count("a")
1
>>> l.count("b")
2

การนับจำนวนที่เกิดขึ้นของรายการทั้งหมดในรายการนั้นเป็นที่รู้จักกันในชื่อ "รับทราบ" รายการหรือสร้างตัวนับรวม

การนับรายการทั้งหมดด้วยการนับ ()

ในการนับการเกิดขึ้นของรายการใน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]

32
Counterเป็นวิธีที่เร็วกว่าสำหรับรายการที่ใหญ่กว่า รายการความเข้าใจวิธีการคือ O (n ^ 2) Counterควรเป็น O (n)
fhucho

20
ตัวนับไม่ได้เร็วขึ้นโดยปัจจัย 2 ตัวนับนั้นเร็วขึ้นด้วยตัวคูณ n (O (n ^ 2) เทียบกับ O (n))
Martijn Pieters

ฉันได้พบว่าเมื่อใช้เป็นจำนวนมากนี้ (พูดคุยเกี่ยวกับล้านของสตริง) isinstanceว่ามันจะช้ามากเพราะการเรียกไปยัง ดังนั้นหากคุณแน่ใจเกี่ยวกับข้อมูลที่คุณกำลังทำงานอยู่อาจเป็นการดีกว่าถ้าคุณเขียนฟังก์ชันแบบกำหนดเองโดยไม่ต้องตรวจสอบประเภทและอินสแตนซ์
Bram Vanroy

66

อีกวิธีในการรับจำนวนการเกิดของแต่ละรายการในพจนานุกรม:

dict((i, a.count(i)) for i in a)

49
ดูเหมือนว่าหนึ่งในโครงสร้างที่ฉันมักจะเกิดขึ้นในการต่อสู้ แต่มันจะวิ่งผ่าน len (a) ครั้งซึ่งหมายถึงความซับซ้อนรันไทม์กำลังสอง (ขณะที่การวิ่งแต่ละครั้งขึ้นอยู่กับ len (a) อีกครั้ง)
Nicolas78

5
dict ((i, a.count (i)) สำหรับ i ใน set (a)) ถูกต้องและเร็วกว่านี้ไหม
hugo24

6
@ hugo24: เล็กน้อย แต่มันจะไม่เร็วกว่าปกติในกรณีที่แย่ที่สุด asymptotically; มันจะn * (number of different items)ดำเนินการไม่นับเวลาที่ใช้ในการสร้างชุด การใช้collections.Counterดีกว่ามากจริงๆ
Clément

ช้ามากไปงานปาร์ตี้ แต่จะไม่ทำตามรหัสจะเกิดข้อผิดพลาดหากรายการมีมากกว่าหนึ่งอินสแตนซ์iเพราะจะพยายามป้อนหลายคีย์ที่มีค่าเดียวกันในพจนานุกรม dict((i, a.count(i)) for i in a)
rp1


45

ให้รายการฉันจะนับเหตุการณ์ที่เกิดขึ้นในรายการใน 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

แล้วมีคอลเลกชันเคาน์เตอร์ คุณสามารถถ่ายโอน iterable ใด ๆ ลงในตัวนับไม่เพียง แต่รายการและตัวนับจะเก็บโครงสร้างข้อมูลของการนับองค์ประกอบ

การใช้งาน:

>>> from collections import Counter
>>> c = Counter(l)
>>> c['b']
4

ตัวนับขึ้นอยู่กับพจนานุกรม Python คีย์เหล่านี้เป็นองค์ประกอบดังนั้นคีย์จำเป็นต้องแฮช โดยทั่วไปจะเป็นชุดที่อนุญาตให้มีองค์ประกอบที่ซ้ำซ้อนในพวกเขา

การใช้งานต่อไปของ collections.Counter

คุณสามารถเพิ่มหรือลบด้วย iterables จากเคาน์เตอร์ของคุณ:

>>> 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})

ทำไมไม่แพนด้า

คำตอบอีกข้อเสนอแนะ:

ทำไมไม่ใช้แพนด้า

Pandas เป็นห้องสมุดทั่วไป แต่ไม่ได้อยู่ในห้องสมุดมาตรฐาน การเพิ่มเป็นความต้องการนั้นไม่สำคัญ

มีโซลูชันในตัวสำหรับกรณีการใช้งานนี้ในรายการวัตถุเองเช่นเดียวกับในไลบรารีมาตรฐาน

หากโครงการของคุณไม่ได้ต้องการแพนด้าแล้วมันก็เป็นเรื่องโง่ที่จะทำให้มันเป็นข้อกำหนดสำหรับฟังก์ชั่นนี้


4
ในขณะที่ "ทำไมไม่ใช่ Pandas" ก็ควรจะมาพร้อมกับ "เมื่อใช้ NumPy" เช่นสำหรับอาร์เรย์ตัวเลขขนาดใหญ่ ปัจจัยในการตัดสินใจไม่ได้เป็นเพียงข้อ จำกัด ของโครงการ แต่มีประสิทธิภาพของหน่วยความจำด้วย NumPy ซึ่งเห็นได้ชัดกับข้อมูลขนาดใหญ่
jpp

ขอบคุณสำหรับการกล่าวถึงหมีแพนด้า / ฯลฯ เป็นการพึ่งพาอย่างจริงจัง แพคเกจเหล่านี้บางส่วนมีผลข้างเคียงเชิงลบ ดังนั้นการเพิ่มสินทรัพย์เหล่านี้สำหรับความต้องการเล็กน้อยสามารถใช้เวลาและเงินจำนวนมาก ส่วนตัวฉันมีประสบการณ์ Numpy และ SciPi เพิ่ม 30 นาทีไปยัง CI ไปป์ไลน์ของเราและใช้เวลาหลายวันกว่าจะได้รับแพ็คเกจแคชอย่างถูกต้อง แพ็คเกจยอดเยี่ยม แต่บางครั้งก็มีค่าใช้จ่ายแอบแฝง +1 แล้ว
Marc

36

ฉันได้เปรียบเทียบโซลูชันที่แนะนำทั้งหมด (และโซลูชันใหม่สองสามรายการ) กับ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,
    )

7
numpy.bincount () จะทำงานกับรายการที่มีรายการ int เท่านั้น
Mukarram Pasha

35

ถ้าคุณต้องการที่จะนับค่าทั้งหมดในครั้งเดียวคุณสามารถทำได้อย่างรวดเร็วโดยใช้อาร์เรย์bincountที่ไม่มีค่า

import numpy as np
a = np.array([1, 2, 3, 4, 1, 4, 1])
np.bincount(a)

ซึ่งจะช่วยให้

>>> array([0, 3, 1, 1, 2])

19

หากคุณสามารถใช้งาน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]]

แพนด้ามีค่าใช้จ่ายมากมายดังนั้นมันจึงเป็นทางออกที่ช้าที่สุดที่มีข้อมูลจำนวนน้อย stackoverflow.com/a/46195192/125507
endolith

14

ทำไมไม่ใช้หมีแพนด้า

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

หากคุณกำลังมองหาองค์ประกอบจำนวนหนึ่งให้พูดaลองดู:

my_count['a']

เอาท์พุท:

3

13

ฉันมีปัญหานี้ในวันนี้และแก้ไขปัญหาของตัวเองก่อนที่จะคิดเพื่อตรวจสอบ นี้:

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

จริง ๆ แล้วเร็วกว่าโซลูชันตัวนับอย่างน้อย Python 2.7


1
เคาน์เตอร์เรียงลำดับรายการในขณะที่คุณไม่ได้ดังนั้นความเร็วที่แตกต่าง (จริงในเวลาที่เขียนไม่แน่ใจว่าเป็นเมื่อคุณเขียนคำตอบยังคงมันอาจจะเกี่ยวข้องกับคนเลื่อนลง)
chaosflaws

3
ตัวนับใน Python 2 นั้นช้านิดหน่อยใช่ มันใช้รหัสที่ปรับให้เหมาะสมกับ C เพื่อทำการนับใน Python 3 และตอนนี้ก็เต้นวนได้ง่าย
Martijn Pieters

12
# 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)]

2
@plaes: เป็นอย่างไร ถ้าโดย 'enterprisey' คุณหมายถึง "เอกสาร" เพื่อเตรียมการสำหรับบันทึกย่อ Py3k ฉันเห็นด้วย
Wes Turner

1
นี่เป็นตัวอย่างที่ดีมากเนื่องจากฉันกำลังพัฒนาเป็นส่วนใหญ่ใน 2.7 แต่ต้องมีเส้นทางการโยกย้ายเป็น 2.4
Adam Lewis

9

ด้านล่างคือคำตอบสามข้อ:

เร็วที่สุดคือใช้สำหรับลูปและเก็บไว้ใน 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

9

นับองค์ประกอบทั้งหมดด้วย itertools.groupby()

possiblity Antoher 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โซลูชัน แต่มันแสดงไว้ที่นี่เพื่อวาดขนานกับตัวอย่างการนับที่ซ้ำกัน


7

แนะนำให้ใช้bincountของ numpy แต่ใช้งานได้กับ 1d arrays ที่มีจำนวนเต็มเท่านั้น นอกจากนี้อาเรย์ที่เกิดขึ้นอาจทำให้เกิดความสับสน (มันมีจำนวนเต็มตั้งแต่นาทีถึงสูงสุดของรายการดั้งเดิมและตั้งค่าเป็น 0 จำนวนเต็มที่หายไป)

วิธีที่ดีกว่าที่จะทำกับ numpy คือการใช้ฟังก์ชั่นที่ไม่ซ้ำกับแอตทริบิวต์ที่return_countsตั้งค่าเป็น True มันส่งคืน tuple ด้วยอาร์เรย์ของค่าที่ไม่ซ้ำกันและอาร์เรย์ของการเกิดขึ้นของแต่ละค่าที่ไม่ซ้ำกัน

# 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}

6

หากต้องการนับจำนวนองค์ประกอบที่หลากหลายที่มีประเภททั่วไป:

li = ['A0','c5','A8','A2','A5','c2','A3','A9']

print sum(1 for el in li if el[0]=='A' and el[1] in '01234')

จะช่วยให้

3 ไม่ใช่ 6


4

แม้ว่ามันจะเป็นคำถามที่เก่ามาก แต่เนื่องจากฉันไม่พบสายการบินหนึ่งฉันจึงทำอย่างใดอย่างหนึ่ง

# 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)

อย่าใช้ความเข้าใจในรายการสำหรับผลข้างเคียง ดู: เป็น Pythonic ที่ใช้ความเข้าใจในรายการเพื่อผลข้างเคียงหรือไม่?
Georgy

3

นอกจากนี้คุณยังสามารถใช้วิธีการในตัวโมดูลcountOfoperator

>>> import operator
>>> operator.countOf([1, 2, 3, 4, 1, 4, 1], 1)
3

1
เป็นวิธีการที่countOfจะดำเนินการ? มันเปรียบเทียบกับความชัดเจนมากขึ้นlist.count(ซึ่งได้ประโยชน์จากการใช้งาน C)? มีข้อดีหรือไม่?
Chris_Rands

2

อาจไม่ได้มีประสิทธิภาพมากที่สุดต้องผ่านพิเศษเพื่อลบรายการที่ซ้ำกัน

ฟังก์ชั่นการใช้งาน:

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}


1

ฉันจะใช้filter()นำตัวอย่างของ Lukasz:

>>> lst = [1, 2, 3, 4, 1, 4, 1]
>>> len(filter(lambda x: x==1, lst))
3

0

หากคุณต้องการจำนวนครั้งสำหรับองค์ประกอบเฉพาะ:

>>> 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])

-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)

3
ในขณะที่รหัสนี้อาจตอบคำถาม แต่มีบริบทเพิ่มเติมเกี่ยวกับสาเหตุและ / หรือวิธีการที่รหัสนี้ตอบคำถามช่วยปรับปรุงมูลค่าระยะยาว
Alex Riabov

-1
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))

สิ่งนี้จะนับซ้ำหรือค้นหารายการในรายการแม้ว่าจะอยู่ในรายการ


ฉันไม่รู้ว่าทำไมบางคนเพียงลงคะแนนให้คำตอบและมันก็มีประโยชน์อย่างสมบูรณ์
Mohamed Fathallah
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.