Python проверяет, одинаковы ли все элементы списка
Как можно проверить python (не проверяя индивидуально каждый элемент, если это возможно), если элементы списка имеют один и тот же тип?
Например, я хотел бы иметь функцию, чтобы проверить, что каждый элемент этого списка является целым (что явно ложно):
x=[1, 2.5, 'a']
def checkIntegers(x):
# return true if all elements are integers, false otherwise
Ответы
Ответ 1
Попробуйте использовать all
в сочетании с isinstance
:
all(isinstance(x, int) for x in lst)
Вы можете даже проверить наличие нескольких типов с помощью isinstance
, если это желательно:
all(isinstance(x, (int, long)) for x in lst)
Не то, чтобы это также захватывало унаследованные классы. например:.
class MyInt(int):
pass
print(isinstance(MyInt('3'),int)) #True
Если вам нужно ограничить себя целыми числами, вы можете использовать all(type(x) is int for x in lst)
. Но это редкий сценарий ОЧЕНЬ.
Функция fun, которую вы могли бы написать, - это та, которая возвращает тип первого элемента в последовательности, если все остальные элементы одного типа:
def homogeneous_type(seq):
iseq = iter(seq)
first_type = type(next(iseq))
return first_type if all( (type(x) is first_type) for x in iseq ) else False
Это будет работать для любых произвольных итераций, но в этом процессе будут использоваться итераторы.
Другая функция fun в том же вене, которая возвращает набор общих оснований:
import inspect
def common_bases(seq):
iseq = iter(seq)
bases = set(inspect.getmro(type(next(iseq))))
for item in iseq:
bases = bases.intersection(inspect.getmro(type(item)))
if not bases:
break
return bases
Ответ 2
Используя any()
, нет необходимости перемещать весь список. Просто перерыв, как только объект, который не является int
или long
, найден:
>>> not any(not isinstance(y,(int,long)) for y in [1,2,3])
True
>>> not any(not isinstance(y,(int,long)) for y in [1,'a',2,3])
False
Ответ 3
>>> def checkInt(l):
return all(isinstance(i, (int, long)) for i in l)
>>> checkInt([1,2,3])
True
>>> checkInt(['a',1,2,3])
False
>>> checkInt([1,2,3,238762384762364892364])
True
Ответ 4
Самый простой способ проверить, состоит ли список из однородных элементов, может быть с функцией groupby модуля itertools:
from itertools import groupby
len(list(groupby(yourlist,lambda i:type(i)))) == 1
Если эта разница отличается от единицы, это означает, что она обнаружила в списке разные типы.
Это связано с тем, что он работает через всю последовательность.
Если вам нужна ленивая версия, вы можете написать для нее функцию:
def same(iterable):
iterable = iter(iterable)
try:
first = type(next(iterable))
return all(isinstance(i,first) for i in iterable)
except StopIteration:
return True
Эта функция хранит тип первого элемента и останавливается, как только он находит другой тип в одном из элементов в списке.
Оба эти метода сильно чувствительны к типу, поэтому он будет видеть как разные int и float, но это должно быть как можно ближе к вашему запросу
ИЗМЕНИТЬ:
заменил цикл for на вызов всем, как было предложено mgilson
в случае итератора void он возвращает True, чтобы быть совместимым с поведением всей функции bulitin
Ответ 5
Объединив некоторые из уже полученных ответов, используя комбинацию map(), type() и set(), вы получите наиболее читаемый ответ imho. Предполагая, что ограничение не проверяет полиморфизм типа, это нормально. Также не самый эффективный с точки зрения вычислений ответ, но он позволяет легко проверить, являются ли все элементы одного и того же типа.
# To check whether all elements in a list are integers
set(map(type, [1,2,3])) == {int}
# To check whether all elements are of the same type
len(set(map(type, [1,2,3]))) == 1
Ответ 6
Вы также можете использовать type()
, если хотите исключить подклассы. См. разницу между isinstance()
и type()
:
>>> not any(not type(y) is int for y in [1, 2, 3])
True
>>> not any(not type(y) == int for y in [1, 'a', 2.3])
False
Хотя вы, возможно, и не захотите, потому что это будет более хрупким. Если y изменяет свой тип на подкласс int, этот код сломается, а isinstance()
будет работать.
Хорошо использовать is
, потому что в памяти есть только один <type 'int'>
, поэтому они должны возвращать тот же идентификатор, если они являются одним и тем же типом.
Ответ 7
def c(x):
for i in x:
if isinstance(i,str):
return False
if isinstance(i,float):
return False
return True
Ответ 8
Я предпочитаю использовать карту для такого случая:
from types import IntType
In [21]: map((lambda x: isinstance(x, IntType)), x)
Out[21]: [True, False, False]