it-swarm.com.de

Python prüft, ob alle Elemente einer Liste vom selben Typ sind

Wie kann in Python geprüft werden (ohne jedes Element einzeln zu prüfen), ob die Elemente einer Liste vom selben Typ sind?

Zum Beispiel würde ich gerne eine Funktion haben, um zu überprüfen, ob jedes Element dieser Liste eine Ganzzahl ist (was eindeutig falsch ist):

x=[1, 2.5, 'a']

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

Versuchen Sie es mit all in Verbindung mit isinstance :

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

Sie können sogar mit isinstance nach mehreren Typen suchen, wenn dies gewünscht ist:

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

Nicht, dass dadurch auch geerbte Klassen erfasst würden. z.B.:

class MyInt(int):
     pass

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

Wenn Sie brauchen, um sich auf ganze Zahlen zu beschränken, können Sie all(type(x) is int for x in lst) verwenden. Aber das ist ein SEHR seltenes Szenario.


Eine lustige Funktion, die Sie damit schreiben können, ist eine, die den Typ des ersten Elements in einer Sequenz zurückgibt, wenn alle anderen Elemente vom selben Typ sind:

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

Dies funktioniert für jede beliebige Iteration, verbraucht jedoch dabei "Iteratoren".

Eine weitere unterhaltsame Funktion in der gleichen Art und Weise, die die Menge der gemeinsamen Basen zurückgibt:

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

90
mgilson

Mit any() müssen Sie nicht die gesamte Liste durchlaufen. Unterbrechen Sie einfach, sobald ein Objekt gefunden wird, das nicht int oder long ist:

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

Die einfachste Möglichkeit, um zu prüfen, ob eine Liste aus omogenen Elementen besteht, kann mit der Groupby-Funktion des itertools-Moduls sein:

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

Wenn sich len von anderen unterscheiden, bedeutet dies, dass verschiedene Typen in der Liste gefunden wurden. Dies hat das Problem, dass die gesamte Sequenz durchlaufen wird. Wenn Sie eine Lazy-Version haben möchten, können Sie dafür eine Funktion schreiben :

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

Diese Funktion speichert den Typ des ersten Elements und stoppt, sobald ein anderer Typ in einem der Elemente in der Liste gefunden wird.

Beide Methoden sind sehr empfindlich für den Typ. Daher werden Int und Float als unterschiedlich betrachtet. Dies sollte jedoch so nahe sein, wie Sie Ihrer Anfrage entsprechen können

BEARBEITEN: 

ersetzte den for-Zyklus durch einen Aufruf an alle, wie von mgilson vorgeschlagen

im Falle eines ungültigen Iterators wird True zurückgegeben, um mit dem Verhalten der Funktion bulitin all übereinzustimmen

1
EnricoGiampieri

Die Kombination einiger bereits gegebener Antworten mit einer Kombination aus map (), type () und set () liefert eine imho eher lesbare Antwort. Angenommen, die Einschränkung, nicht auf Typ-Polymorphismen zu prüfen, ist in Ordnung. Es ist auch nicht die effizienteste Antwort, aber es lässt sich leicht überprüfen, ob alle Elemente vom gleichen Typ sind.

# 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

Sie können auch type() verwenden, wenn Sie Unterklassen ausschließen möchten. Siehe den Unterschied zwischen isinstance() und 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

Vielleicht möchten Sie dies nicht, weil dies anfälliger sein wird. Wenn y seinen Typ in eine Unterklasse von int ändert, wird dieser Code beschädigt, wohingegen isinstance() weiterhin funktioniert.

Die Verwendung von is ist in Ordnung, da sich nur ein <type 'int'> im Speicher befindet. Daher sollten sie dieselbe Identität zurückgeben, wenn sie vom gleichen Typ sind.

0
Mark Mikofski