Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Python

Python: นับความถี่ (Frequency) ในลิสต์ด้วย Dictionary และ Counter

การนับความถี่ขององค์ประกอบในลิสต์ (Frequency Counting) เป็น Operation พื้นฐานใน Data Analysis Python มีหลายวิธี ตั้งแต่ Manual ไปจนถึง Built-in Tools

วิธีที่ 1: Dictionary แบบ Manual (เข้าใจ Logic)

items = ['a', 'b', 'a', 'c', 'd', 'c', 'c']

frequency = {}
for item in items:
    if item in frequency:
        frequency[item] += 1
    else:
        frequency[item] = 1

print(frequency)  # {'a': 2, 'b': 1, 'c': 3, 'd': 1}

# แสดงผลสวย
for key, value in frequency.items():
    print(f"{key} -> {value}")

วิธีที่ 2: ใช้ dict.get() (สั้นกว่า)

frequency = {}
for item in items:
    frequency[item] = frequency.get(item, 0) + 1

print(frequency)  # {'a': 2, 'b': 1, 'c': 3, 'd': 1}

วิธีที่ 3: ใช้ collections.Counter (แนะนำ - Pythonic & Fast)

from collections import Counter

items = ['a', 'b', 'a', 'c', 'd', 'c', 'c']
frequency = Counter(items)

print(frequency)           # Counter({'c': 3, 'a': 2, 'b': 1, 'd': 1})
print(dict(frequency))     # {'a': 2, 'b': 1, 'c': 3, 'd': 1}

# Most Common
print(frequency.most_common(2))  # [('c', 3), ('a', 2)]
print(frequency.most_common())   # All sorted by count

วิธีที่ 4: ใช้ list.count() (Simple แต่ช้า O(n²))

items = ['a', 'b', 'a', 'c', 'd', 'c', 'c']

frequency = {}
for item in items:
    frequency[item] = items.count(item)

print(frequency)  # {'a': 2, 'b': 1, 'c': 3, 'd': 1}
# ⚠️ เรียก count() ทุก Loop -> O(n²) ไม่แนะนำสำหรับ List ใหญ่

วิธีที่ 5: ใช้ defaultdict (Clean Code)

from collections import defaultdict

frequency = defaultdict(int)
for item in items:
    frequency[item] += 1

print(dict(frequency))  # {'a': 2, 'b': 1, 'c': 3, 'd': 1}

Performance Comparison

import timeit
import random
import string
from collections import Counter, defaultdict

# Large List: 100,000 items
large_list = [random.choice(string.ascii_letters) for _ in range(100_000)]

methods = {
    "Manual if/else": "freq={}; [freq.__setitem__(x, freq.get(x,0)+1) for x in large_list]",
    "dict.get": "freq={}; [freq.__setitem__(x, freq.get(x,0)+1) for x in large_list]",
    "Counter": "Counter(large_list)",
    "defaultdict": "from collections import defaultdict; freq=defaultdict(int); [freq.__setitem__(x, freq[x]+1) for x in large_list]",
    "count()": "freq={}; [freq.__setitem__(x, large_list.count(x)) for x in large_list]",
}

for name, code in methods.items():
    # Setup code for timeit
    setup = "from collections import Counter, defaultdict; import random, string; large_list = [random.choice(string.ascii_letters) for _ in range(100000)]"
    time = timeit.timeit(code, setup=setup, number=10)
    print(f"{name:20}: {time:.4f}s")

ผลลัพธ์ทั่วไป

Manual if/else      : 0.4500s
dict.get            : 0.4200s
Counter             : 0.0800s  (เร็วที่สุด - C Implementation)
defaultdict         : 0.3800s
count()             : 45.000s  (ช้ามาก O(n²))

Advanced Counter Operations

from collections import Counter

c1 = Counter(a=3, b=2, c=1)
c2 = Counter(a=1, b=2, d=4)

print("c1:", c1)           # Counter({'a': 3, 'b': 2, 'c': 1})
print("c2:", c2)           # Counter({'d': 4, 'b': 2, 'a': 1})

# Arithmetic
print("c1 + c2:", c1 + c2)  # Counter({'a': 4, 'b': 4, 'd': 4, 'c': 1})
print("c1 - c2:", c1 - c2)  # Counter({'a': 2, 'c': 1})  (Only positive counts)
print("c1 & c2:", c1 & c2)  # Counter({'b': 2, 'a': 1})  (Intersection: min)
print("c1 | c2:", c1 | c2)  # Counter({'d': 4, 'a': 3, 'b': 2, 'c': 1}) (Union: max)

# Elements (Expand to List)
print("list(c1.elements()):", list(c1.elements()))  # ['a','a','a','b','b','c']

# Subtract (In-place, allows negative)
c1.subtract(c2)
print("c1 after subtract:", c1)  # Counter({'a': 2, 'c': 1, 'b': 0, 'd': -4})

การประยุกต์ใช้งานจริง

1. Word Frequency Analysis

text = "the quick brown fox jumps over the lazy dog the quick fox"
words = text.split()
word_freq = Counter(words)
print(word_freq.most_common(3))  # [('the', 3), ('quick', 2), ('fox', 2)]

2. Character Frequency (สำหรับ Cryptanalysis, Compression)

text = "hello world"
char_freq = Counter(text.replace(" ", ""))  # Ignore spaces
print(char_freq.most_common())  # [('l', 3), ('o', 2), ('h', 1), ('e', 1), ('w', 1), ('r', 1), ('d', 1)]

3. Find Duplicates (จากบทความก่อนหน้า)

def find_duplicates(items):
    return [item for item, count in Counter(items).items() if count > 1]

print(find_duplicates([1,2,3,2,4,3,5]))  # [2, 3]

สรุป

วิธีSpeedCode ClarityFeaturesแนะนำ
Manual DictSlowGoodBasicLearning
dict.get()SlowGoodBasicSimple Scripts
CounterFastest (C)BestRich (most_common, arithmetic, elements)Production ✅
defaultdictMediumGoodAuto-initCustom Logic
list.count()Very Slow (O(n²))SimpleNoneAvoid