可能であればすべての要素を個別にチェックせずに、リストの要素が同じタイプであるかどうかを確認するにはどうすればよいですか?
たとえば、このリストのすべての要素が整数(明らかにfalse)であることを確認する関数が必要です。
x = [1, 2.5, 'a']
def checkIntegers(x):
# return True if all elements are integers, False otherwise
可能であればすべての要素を個別にチェックせずに、リストの要素が同じタイプであるかどうかを確認するにはどうすればよいですか?
たとえば、このリストのすべての要素が整数(明らかにfalse)であることを確認する関数が必要です。
x = [1, 2.5, 'a']
def checkIntegers(x):
# return True if all elements are integers, False otherwise
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)
。しかし、それは非常にまれなシナリオです。
これを使用して記述できる楽しい関数は、他のすべての要素が同じタイプである場合に、シーケンスの最初の要素のタイプを返す関数です。
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
を使用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
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
>>> 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
リストが同種の要素で構成されているかどうかを確認する最も簡単な方法は、itertoolsモジュールのgroupby関数を使用することです。
from itertools import groupby
len(list(groupby(yourlist,lambda i:type(i)))) == 1
th lenが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
この関数は、最初の要素のタイプを格納し、リスト内の要素の1つで別のタイプが見つかるとすぐに停止します。
このメソッドは両方とも型に非常に敏感であるため、異なるintとfloatとして表示されますが、これは要求にできるだけ近づける必要があります
編集:
mgilsonによって提案されたように、forサイクルをallへの呼び出しに置き換えました
void iteratorの場合、それはTrueを返し、bulitinall関数の動作と一致します。
このメソッドを使用することをお勧めします。このメソッドでは、リスト内の各項目を繰り返し処理し、それらがすべて同じデータ型であるかどうかを確認します。はいの場合はTrue、それ以外の場合はFalseを返します。
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
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
メモリには1つしかないため、使用しても問題あり<type 'int'>
ません。同じタイプの場合は、同じIDを返す必要があります。
EnricoGiampieri(上記)の関数が好きですが、ドキュメントの「Itertoolsレシピ」セクション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
ます。
実質的にすべてのこれらのレシピと他の多くのレシピは、PythonPackageIndexにあるmore-itertoolsプロジェクトからインストールできます。
pip install more-itertools
拡張ツールは、基盤となるツールセットと同じ高性能を提供します。反復可能オブジェクト全体を一度にメモリに取り込むのではなく、要素を1つずつ処理することで、優れたメモリパフォーマンスが維持されます。一時変数を排除するのに役立つ機能的なスタイルでツールをリンクすることにより、コードの量を少なく抑えます。インタープリターのオーバーヘッドが発生するforループやジェネレーターを使用するよりも、「ベクトル化された」ビルディングブロックを優先することで、高速性が維持されます。
from more_itertools import all_equal
all_equal(map(type, iterable))
またisinstance
はと既知のタイプint
(元の質問による)
all_equal(map(lambda x: isinstance(x, int), iterable))
これらの2つの方法は、Enricoの提案よりも簡潔でありrange(0)
、Enricoの関数と同じように「voidイテレータ」(たとえば)を処理します。
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
これに関する簡潔な関数を次に示します。現在、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']
def c(x):
for i in x:
if isinstance(i,str):
return False
if isinstance(i,float):
return False
return True
私はこのような場合にマップを使用することを好みます:
from types import IntType
In [21]: map((lambda x: isinstance(x, IntType)), x)
Out[21]: [True, False, False]