web-dev-qa-db-fra.com

Python vérifie si tous les éléments d'une liste sont du même type

Comment est-il possible en python de vérifier (sans vérifier individuellement chaque élément si possible) si les éléments d'une liste sont du même type?

Par exemple, je voudrais avoir une fonction pour vérifier que chaque élément de cette liste est un entier (ce qui est clairement faux):

x=[1, 2.5, 'a']

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

Essayez d’utiliser all en conjonction avec isinstance :

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

Vous pouvez même vérifier plusieurs types avec isinstance si cela est souhaitable:

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

Non pas que cela ramassera aussi les classes héritées. par exemple.:

class MyInt(int):
     pass

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

Si vous devez vous limiter à des entiers, vous pouvez utiliser all(type(x) is int for x in lst). Mais c’est un scénario rare, le TRÈS.


Une fonction amusante avec laquelle vous pourriez écrire est celle qui renverrait le type du premier élément d'une séquence si tous les autres éléments sont du même type:

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

Cela fonctionnera pour n'importe quelle itération arbitraire, mais cela consommera des "itérateurs" dans le processus. 

Une autre fonction amusante dans la même veine qui renvoie l’ensemble des bases communes:

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

82
mgilson

Avec any() , inutile de parcourir toute la liste. Juste casser dès que l'objet qui n'est pas int ou long est trouvé:

>>> 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
2
Inbar Rose

Le moyen le plus simple de vérifier si une liste est composée d'éléments omogènes peut être avec la fonction groupby du module itertools:

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

Si cela est différent de l'un, cela signifie qu'il a trouvé différents types de types dans la liste . Cela pose le problème de parcourir toute la séquence . Si vous voulez une version paresseuse, vous pouvez écrire une fonction pour cela :

def same(iterable):
    iterable = iter(iterable)
    try:
        first = type(next(iterable))
        return all(isinstance(i,first) for i in iterable)
    except StopIteration:
        return True

Cette fonction enregistre le type du premier élément et s’arrête dès qu’il trouve un type différent dans l’un des éléments de la liste.

Ces deux méthodes sont très sensibles au type, elles apparaîtront donc de manière différente en tant que int et float, mais cela devrait être aussi proche que possible de votre demande.

MODIFIER: 

remplacé le pour cycle par un appel à tous comme suggéré par mgilson

en cas d'itérateur vide, il retourne True pour être cohérent avec le comportement de la fonction bulitin

1
EnricoGiampieri

En combinant certaines des réponses déjà données, en combinant map (), type () et set (), on obtient une réponse plutôt lisible. En supposant que la limitation de ne pas vérifier les polymorphismes de type est ok. Ce n’est pas non plus la réponse la plus efficace du point de vue informatique, mais elle permet de vérifier facilement si tous les éléments sont du même type.

# 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
1
user1556435

Vous pouvez également utiliser type() si vous souhaitez exclure des sous-classes. Voir la différence entre isinstance() et 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

Bien que vous ne le souhaitiez peut-être pas, cela serait plus fragile. Si y change son type en une sous-classe de int, ce code sera cassé, alors que isinstance() fonctionnera toujours.

Il est correct d'utiliser is car il n'y a qu'un <type 'int'> en mémoire. Ils doivent donc renvoyer la même identité s'ils sont du même type.

0
Mark Mikofski