Python检查列表的所有元素是否都是相同的类型

时间:2012-11-06 13:44:21

标签: python list types

如果列表的元素属于同一类型,python中如何检查(如果可能的话,不单独检查每个元素)?

例如,我想有一个函数来检查这个列表的每个元素是否为整数(显然是错误的):

x=[1, 2.5, 'a']

def checkIntegers(x):
    # return true if all elements are integers, false otherwise

11 个答案:

答案 0 :(得分:89)

尝试将allisinstance结合使用:

all(isinstance(x, int) for x in lst)

如果需要,您甚至可以使用isinstance检查多种类型:

all(isinstance(x, (int, long)) for x in lst)

并不是说这也会获得继承的类。 e.g:

class MyInt(int):
     pass

print(isinstance(MyInt('3'),int)) #True

如果您需要将自己限制为只有整数,则可以使用all(type(x) is int for x in lst)。但这是非常罕见的情况。


如果所有其他元素的类型相同,那么你可以用这个函数写一个有趣的函数,它会返回序列中第一个元素的类型:

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

这适用于任何可任意的迭代,但它会消耗过程中的“迭代器”。

另一个有趣的功能,它返回一组共同的基础:

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

答案 1 :(得分:3)

使用any(),无需遍历整个列表。只要找到不是intlong的对象,就会中断:

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

答案 2 :(得分:2)

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

答案 3 :(得分:1)

检查列表是否由多余元素组成的最简单方法可以是itertools模块的groupby函数:

from itertools import groupby
len(list(groupby(yourlist,lambda i:type(i)))) == 1

如果len不同于它,则意味着它在列表中找到了不同类型的类型。 这具有贯穿整个序列的问题。 如果你想要一个懒惰的版本,你可以为它编写一个函数:

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,但这应该尽可能接近你的请求

编辑:

按照mgilson

的建议,通过调用all来替换for循环

在void迭代器的情况下,它返回True以与bulitin all函数的行为一致

答案 4 :(得分:1)

结合已经给出的一些答案,使用map(),type()和set()的组合提供了一个非常可读的答案。假设不检查类型多态性的限制是可以的。也不是计算效率最高的答案,但它可以轻松检查所有元素是否属于同一类型。

# 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

答案 5 :(得分:0)

如果要排除子类,也可以使用type()。见the difference between isinstance() and 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'>,所以如果它们属于同一类型,它们应该返回相同的标识。

答案 6 :(得分:0)

我喜欢 EnricoGiampieri above)的函数,但是有一个使用Itertools recipes” all_equal的简单版本itertools文档的>部分:

from itertools import groupby

def all_equal(iterable):
    "Returns True if all the elements are equal to each other"
    g = groupby(iterable)
    return next(g, True) and not next(g, False)

所有这些食谱均在more_itertools中的packaged中:

基本上所有这些食谱以及许多其他食谱都可以从Python Package Index上的more-itertools项目中安装:

pip install more-itertools

扩展工具提供与基础工具集相同的高性能。通过一次处理一个元素,而不是一次将整个可迭代对象全部放入内存,可以保持卓越的内存性能。通过以一种功能样式将工具链接在一起,可以减少代码量,这有助于消除临时变量。与使用for循环和生成器相比,首选“向量化”构建块来保持高速,这会产生解释器开销。

from more_itertools import all_equal

all_equal(map(type, iterable))

或具有isinstance和已知类型int(根据原始问题)

all_equal(map(lambda x: isinstance(x, int), iterable))

这两种方法比Enrico的建议更简洁,并且像Enrico的函数一样处理“无效迭代器”(例如range(0))。

all_equal(map(type, range(0))) # True
all_equal(map(type, range(1))) # True
all_equal(map(type, range(2))) # True

all_equal(map(lambda x: isinstance(x, int), range(0))) # True
all_equal(map(lambda x: isinstance(x, int), range(1))) # True
all_equal(map(lambda x: isinstance(x, int), range(2))) # True

答案 7 :(得分:0)

我更喜欢你使用这种方法,你遍历列表中的每个项目并检查它们是否都是相同的数据类型,如果是,则返回真,否则返回假。

def checkIntegers(x):
    # return True if all elements are integers, False otherwise
    return all(isinstance(i, type(x[0])) for i in x[1:])

x = [1, 2.5, 'a']
checkIntegers(x)

False

答案 8 :(得分:0)

这是一个关于此的简明函数,目前它检查(在 list 中)是否所有项目都是整数,或者所有项目是否都是字符串,或者如果混合数据类型

def check_item_dtype_in_list(item_range):
    if all(map(lambda x: str(x).isdigit(), item_range)):
        item_range = list(map(int, item_range))
        print('all are integer')
        print(item_range)
        return 
    elif all(isinstance(item, str) for item in item_range):
        print('all are string')
        print(item_range)
        return 
    elif any(map(lambda x: str(x), item_range)):
        print('mixed dtype')
        print(item_range)
        return 
check_item_dtype_in_list(['2', 2, 3])
check_item_dtype_in_list(["2", 2, 'Two'])
check_item_dtype_in_list(['Two', 'Two', 'Two'])
check_item_dtype_in_list([2, 2., 'Two'])
all are integer
[2, 2, 3]
mixed dtype
['2', 2, 'Two']
all are string
['Two', 'Two', 'Two']
mixed dtype
[2, 2.0, 'Two']

答案 9 :(得分:-1)

    def c(x):
         for i in x:
             if isinstance(i,str):
                   return False
             if isinstance(i,float):
                   return False

          return True

答案 10 :(得分:-1)

我更喜欢将地图用于这样的案例:

from types import IntType
In [21]: map((lambda x: isinstance(x, IntType)), x)
   Out[21]: [True, False, False]