Определение количества числовых элементов в списке языка Python
Количество чисел в списке Python
При работе со списками часто возникает необходимость узнать, сколько элементов списка являются числами (целыми или с плавающей точкой). Это может потребоваться при очистке данных, проверке типов или статистическом анализе. В статье рассматриваются различные подходы к решению этой задачи, их преимущества и возможные ошибки.
Самый эффективный способ: генератор с sum и isinstance
Цель: получить количество чисел в списке за минимальное время и с минимальным объёмом кода.
lst = [1, 2.5, 'abc', None, True, 3, 4.0]
count = sum(1 for x in lst if isinstance(x, (int, float)))
print(count) # 4 (1, 2.5, 3, 4.0)посчитать список python (посчитать элементы списка в python)
Используется sum с генератором, который выдаёт единицу для каждого элемента, являющегося числом. Функция isinstance проверяет принадлежность к кортежу типов (int, float). Это решение работает быстро, не создаёт промежуточных списков и легко читается.
Проблема: логическое значение True и False считаются подтипом int в Python. Если требуется исключить булевы значения, необходимо добавить дополнительное условие: type(x) in (int, float) или isinstance(x, (int, float)) and not isinstance(x, bool). В примере выше True будет учтён как число, что может быть нежелательно.
Как подсчитать количество чисел через цикл for и условный оператор?
Цель: явный контроль над каждым элементом, возможность выполнить дополнительные действия при проверке.
lst = [1, 2.5, 'abc', None, True, 3]
count = 0
for x in lst:
if isinstance(x, (int, float)):
count += 1
print(count) # 4функция длина списка в python (длина списка в python)
Этот вариант даёт полную гибкость: внутри цикла можно добавить логирование, модификацию элементов или подсчёт по нескольким условиям. Однако он более громоздкий и медленнее генератора на больших списках.
Типичная ошибка: забыть инициализировать счётчик нулём или написать if type(x) == int or type(x) == float. В последнем случае для подклассов int или float проверка не пройдёт, а для булевых значений они пройдут, так как type(True) возвращает bool, а не int. Использование isinstance решает обе проблемы.
Как применить filter и len для подсчёта чисел?
Цель: использовать функциональный стиль программирования.
lst = [1, 2.5, 'abc', None, True, 3]
filtered = filter(lambda x: isinstance(x, (int, float)), lst)
count = len(list(filtered))
print(count) # 4
количество чисел python (количество чисел в python)
filter возвращает итератор, поэтому для получения длины требуется преобразование в список. Недостаток – создаётся промежуточный список, что увеличивает потребление памяти.
Проблема: если список очень большой, преобразование итератора в список может привести к значительному расходу памяти. В таких случаях лучше использовать генератор с sum.
Как использовать list comprehension для подсчёта чисел?
Цель: наглядное создание списка чисел с последующим вычислением длины.
lst = [1, 2.5, 'abc', None, True, 3]
numbers = [x for x in lst if isinstance(x, (int, float))]
count = len(numbers)
print(count) # 4
print(numbers) # [1, 2.5, 3] - True исключён, так как isinstance(True, (int,float)) даёт True, но в коде выше мы этого не учитываем. Для исключения bool: [x for x in lst if isinstance(x, (int,float)) and not isinstance(x,bool)]получить индекс python (получение индекса элемента в python)
Этот способ удобен, когда нужен не только счёт, но и сам список чисел для дальнейшей обработки. Однако он всегда создаёт полный список в памяти.
Ошибка: новички часто пишут if type(x) == int or float. Такая запись всегда верна, так как float – ненулевое значение, трактуемое как истина. Правильно: if type(x) == int or type(x) == float или лучше isinstance(x, (int, float)).
Можно ли подсчитать количество чисел с помощью метода count?
Цель: использовать встроенную функцию для подсчёта вхождений конкретного значения.
lst = [1, 1.5, 1, 2, 'a']
print(lst.count(1)) # 2 (считает только целые 1)
print(lst.count(1.5)) # 1
count не предназначен для подсчёта всех чисел different типов. Он считает только точные совпадения. Этот подход не решает задачу, если список содержит числа разных типов или значений.
Неверное использование: попытка lst.count(int) вызовет ошибку, так как int – это тип, а не элемент списка. count ожидает конкретное значение, а не тип.
Расширенные примеры подсчёта чисел в списке
Пример 1. Подсчёт чисел с исключением булевых значений
lst = [0, 1, True, False, 2.5, 'строка', None]
# Вариант с type
count_type = sum(1 for x in lst if type(x) in (int, float))
print(count_type) # 3 (0, 1, 2.5) - True и False пропущены, так как их типы bool, а не int
# Вариант с isinstance и дополнительной проверкой
count_isinstance = sum(1 for x in lst if isinstance(x, (int, float)) and not isinstance(x, bool))
print(count_isinstance) # 3
3 3
Пример 2. Подсчёт чисел, удовлетворяющих условию (больше нуля)
lst = [-1, 0, 3.14, 5, -2.5, 10]
positive_count = sum(1 for x in lst if isinstance(x, (int, float)) and x > 0)
print(positive_count) # 3 (3.14, 5, 10)
3
Пример 3. Подсчёт чисел во вложенных списках (рекурсивный подход)
def count_numbers_nested(lst):
total = 0
for item in lst:
if isinstance(item, (int, float)):
total += 1
elif isinstance(item, list):
total += count_numbers_nested(item)
return total
nested = [1, [2.5, 'abc'], [3, [4, 5.0]]]
print(count_numbers_nested(nested)) # 5
5
Пример 4. Использование map и sum для подсчёта чисел
lst = [1, 2.5, 'a', 3, None]
# map возвращает итератор булевых значений, sum считает True как 1
count = sum(map(lambda x: isinstance(x, (int, float)), lst))
print(count) # 3
3
Пример 5. Сравнение производительности различных методов (timeit)
import timeit
lst = [i if i % 2 == 0 else str(i) for i in range(1000)] # смесь чисел и строк
# Генератор с sum
t1 = timeit.timeit('sum(1 for x in lst if isinstance(x, (int, float)))', globals=globals(), number=10000)
# Цикл for
def count_loop(lst):
c = 0
for x in lst:
if isinstance(x, (int, float)):
c += 1
return c
t2 = timeit.timeit('count_loop(lst)', globals=globals(), number=10000)
# filter + len
t3 = timeit.timeit('len(list(filter(lambda x: isinstance(x, (int, float)), lst)))', globals=globals(), number=10000)
# list comprehension + len
t4 = timeit.timeit('len([x for x in lst if isinstance(x, (int, float))])', globals=globals(), number=10000)
print(f"generator+sum: {t1:.3f}")
print(f"for loop: {t2:.3f}")
print(f"filter+len: {t3:.3f}")
print(f"list comp+len: {t4:.3f}")
generator+sum: 0.123 for loop: 0.156 filter+len: 0.195 list comp+len: 0.187
(Результаты могут отличаться в зависимости от системы, но генератор с sum обычно оказывается быстрее.)
Пример 6. Подсчёт чисел с использованием collections.Counter
from collections import Counter
lst = [1, 'a', 2.5, 1, True, 3.0]
c = Counter(type(x).__name__ for x in lst)
# Количество элементов, принадлежащих типам int или float
count = c['int'] + c['float']
print(c) # Counter({'int': 2, 'str': 1, 'float': 2, 'bool': 1})
print(count) # 4 (оба int – 1 и 1, оба float – 2.5 и 3.0)
Counter({'int': 2, 'str': 1, 'float': 2, 'bool': 1})
4
Пример 7. Подсчёт чисел с игнорированием строковых представлений чисел
import re
lst = ['123', '4.5', 'abc', 6, 7.0]
# Только элементы, уже являющиеся числами
count_numeric = sum(1 for x in lst if isinstance(x, (int, float)))
print(count_numeric) # 2
# Если нужно учитывать и строки, которые можно преобразовать в число:
def is_numeric_str(s):
try:
float(s)
return True
except:
return False
count_all = sum(1 for x in lst if isinstance(x, (int, float)) or (isinstance(x, str) and is_numeric_str(x)))
print(count_all) # 4 ('123', '4.5', 6, 7.0)
2 4