Разбор: Охота на смайлики 🕵️‍♂️

Давай посмотрим на присланное решение:

import re

def num_emojis(arg):
return sum([re.match("^[:;][~-]?[)D]$",i) is not None for i in arg])


Работает? Да. Оставлять такое в проде? Нет.

1️⃣ Грех аллокации
Квадратные скобки внутри sum([ ... ]) означают, что Питон сначала создаст в памяти полный список из True/False размером с исходный массив, и только потом его просуммирует. Если на вход прилетит лог на 10 миллионов строк, ваша память выйдет из чата.
Убираем скобки — получаем генераторное выражение. Память O(1) вместо O(n).

2️⃣ Избыточные проверки
Конструкция match(...) is not None имеет право на жизнь, но в Питоне принято использовать встроенную "правдивость" (truthiness) объектов. Плюс, нам нужно просто посчитать количество совпадений. Идиоматичный подход: sum(1 for ... if ...)

3️⃣ Перекомпиляция
Вызов re.match внутри цикла каждый раз заставляет Python лезть в кэш регулярок. Если строк много, паттерн нужно компилировать один раз до цикла.

Выкидываем мусор и пишем так:
import re

# Выносим компиляцию наверх
SMILEY_PATTERN = re.compile(r"^[:;][~-]?[)D]$")

def count_smileys(faces: list[str]) -> int:
return sum(1 for face in faces if SMILEY_PATTERN.match(face))


☝️Но главная проблема этого решения не в синтаксисе.
Зачем нам вообще тут регулярки?

Давайте посчитаем: у нас 2 варианта глаз, 3 варианта носа (включая его отсутствие) и 2 варианта рта.
Существует ровно 12 валидных смайликов. Как и написал @archimage_wiz, вместо того чтобы на каждой строке запускать тяжелую машину состояний регулярных выражений, нам достаточно проверить вхождение строки в заранее подготовленное множество (set).

Поиск в множестве работает за константное время O(1) (это хэш-таблица).

Решение здорового человека:
from typing import List

VALID_SMILES = {
':)', ';)', ':-)', ';-)', ':~)', ';~)',
':D', ';D', ':-D', ';-D', ':~D', ';~D'
}

def num_emojis_pro(arr: List[str]) -> int:
return sum(s in VALID_SMILES for s in arr)


Этот код не требует импорта модуля re, он очевиден любому джуну с первого взгляда, и на больших объемах данных он уничтожит регулярки по скорости выполнения.

Сложные инструменты — это круто. Но умение обходиться простыми — это уже скилл.

#алгособес