web-dev-qa-db-ja.com

Pythonリスト項目が数字かどうかを確認

文字列形式の数字と文字を含むリストがあります。

mylist=['1','orange','2','3','4','Apple']

数字のみを含む新しいリストを作成する必要があります。

mynewlist=['1','2','3','4']

リスト内の各項目を整数に変換できるかどうかを確認する方法がある場合、次のようなことを実行して、必要なものを見つけることができるはずです。

for item in mylist:
    if (check item can be converted to integer):
        mynewlist.append(item)

文字列が整数に変換できることを確認するにはどうすればよいですか?またはそれを行うためのより良い方法はありますか?

19
Chris Aung

これを試して:

_mynewlist = [s for s in mylist if s.isdigit()]
_

docs から:

str.isdigit()

文字列内のすべての文字が数字で、少なくとも1つの文字がある場合はtrueを返し、そうでない場合はfalseを返します。

8ビット文字列の場合、このメソッドはロケールに依存します。


コメントに記載されているように、isdigit()Trueを返すことは、文字列がint()関数を介してintとして解析できることを必ずしも示しておらず、Falseは、必ずしもそうでないことを示すわけではありません。それにもかかわらず、上記のアプローチはあなたのケースで動作するはずです。

31
arshajii

高速でシンプルですが、常に正しいとは限りません。

>>> [x for x in mylist if x.isdigit()]
['1', '2', '3', '4']

数字を取得する必要がある場合のより伝統的な方法:

new_list = []
for value in mylist:
    try:
        new_list.append(int(value))
    except ValueError:
        continue

:結果には整数が含まれます。必要に応じて、上記の行を次の文字列に置き換えて、文字列に変換します。

try:
    new_list.append(str(int(value)))
12
Mike Müller

str.digitは整数に対してのみ機能し、次のような場合にも失敗する可能性があるため、例外処理を使用できます。

>>> str.isdigit(' 1')
False

ジェネレーター関数の使用:

def solve(lis):                                        
    for x in lis:
        try:
            yield float(x)
        except ValueError:    
            pass

>>> mylist = ['1','orange','2','3','4','Apple', '1.5', '2.6']
>>> list(solve(mylist))                                    
[1.0, 2.0, 3.0, 4.0, 1.5, 2.6]   #returns converted values

または、これが欲しいかもしれません:

def solve(lis):
    for x in lis:
        try:
            float(x)
            return True
        except:
            return False
...         
>>> mylist = ['1','orange','2','3','4','Apple', '1.5', '2.6']
>>> [x for x in mylist if solve(x)]
['1', '2', '3', '4', '1.5', '2.6']

またはast.literal_evalを使用すると、これはすべてのタイプの数値で機能します。

>>> from ast import literal_eval
>>> def solve(lis):
    for x in lis:
        try:
            literal_eval(x)
            return True
        except ValueError:   
             return False
...         
>>> mylist=['1','orange','2','3','4','Apple', '1.5', '2.6', '1+0j']
>>> [x for x in mylist if solve(x)]                               
['1', '2', '3', '4', '1.5', '2.6', '1+0j']
10

何かをintに変換できるかどうかを確認する通常の方法は、 [〜#〜] eafp [〜#〜] の原則に従ってtry itを確認することです。

_try:
    int_value = int(string_value)
except ValueError:
    # it wasn't an int, do something appropriate
else:
    # it was an int, do something appropriate
_

だから、あなたの場合:

_for item in mylist:
    try:
        int_value = int(item)
    except ValueError:
        pass
    else:
        mynewlist.append(item) # or append(int_value) if you want numbers
_

ほとんどの場合、mynewlist.append(item)で終わる簡単なコードのループは、リストの内包表記、ジェネレータ式、またはmapまたはfilterの呼び出しに変換できます。しかし、ここではできません。なぜなら、try/exceptを式に入れる方法がないからです。

ただし、関数でラップすると、次のことができます。

_def raises(func, *args, **kw):
    try:
        func(*args, **kw)
    except:
        return True
    else:
        return False

mynewlist = [item for item in mylist if not raises(int, item)]
_

…または、必要に応じて:

_mynewlist = filter(partial(raises, int), item)
_

この方法で使用すると、よりクリーンになります。

_def raises(exception_types, func, *args, **kw):
    try:
        func(*args, **kw)
    except exception_types:
        return True
    else:
        return False
_

この方法では、期待する例外(または例外のタプル)を渡すことができ、それらはTrueを返しますが、unexpected例外がある場合発生すると、伝播します。そう:

_mynewlist = [item for item in mylist if not raises(ValueError, int, item)]
_

…はあなたが望むことをしますが、:

_mynewlist = [item for item in mylist if not raises(ValueError, item, int)]
_

…必要に応じて、TypeErrorを発生させます。

4
abarnert