1

整数である可能性のある部分文字列を含む文字列が多数あります。

mystring = "123 345 456 567 678 789"

そしてそれを確認する必要があります:

a。各部分文字列は実際には整数です。mystring = "123 345 456 567 abc 789"'abc'に達すると失敗します

b。各整数は0<=i<=10000の範囲内にあります。mystring = "123 -345 456 567 678 789"'-345'に達すると失敗します

1つの解決策は次のとおりです。

mylist= [int(i) for i in mystring.split() if isinstance(int(i), int) and (0 <= int(i) <= 10000)]

質問は次のとおりです。

私。リスト内包表記では、iごとに、int(i)が1回または複数回評価されますか?

ii。より高速な代替方法はありますか(文字列のボリュームが大きく、各文字列に数百から数千の整数が含まれる可能性があるため)?

4

5 に答える 5

5

私はおそらく次のようなものを使用すると思います:

try:
    if not all( (0 <= int(i) <= 10000) for i in mystring.split() ):
       raise ValueError("arg!")
except ValueError:
    print "Oops, didn't pass"

intこれには、何かがに変換できない場合、または正しい範囲に収まらない場合に短絡するという利点があります。

これがばかげたテストです:

def test_str(mystring):
    try:
        return all( (0 <= int(i) <= 10000) for i in mystring.split() )
    except ValueError:
        return False

print test_str("123 345 456 567 abc 789")
print test_str("123 345 456 567 -300 789")
print test_str("123 345 456 567 300 789")
于 2013-01-23T20:00:57.437 に答える
1

int(i)複数回評価されます。また、非整数​​入力で例外が発生し、非整数をサイレントに返すのでisinstance(int(i), int)はないため、役に立ちません。int()

昔ながらのループとしてコードを書くことに何の問題もありません。これにより、エラー処理に関して最大​​の柔軟性が得られます。効率が心配な場合は、リスト内包表記はそのようなループの構文糖衣に他ならないことを忘れないでください。

intlist = []
for part in mystring.split():
    try:
        val = int(part)
    except ValueError:
        continue  # or report the error
    if val < 0 or val > 10000:
        continue  # or report the error
    intlist.append(val)
于 2013-01-23T20:03:11.513 に答える
0

正規表現を使用することもできます。

import re
mystring = "123 345 456 567 abc 789 -300 ndas"

re_integer = r'(-??\d+)'
re_space_or_eof = r'(\ |$)' #using space or eof so we don't match floats

#match all integers
matches = re.finditer(re_integer + re_space_or_eof, mystring)

#extract the str, convert to int for all matches
int_matches = [int(num.groups()[0]) for num in matches]

#filter based on criteria
in_range = [rnum for rnum in int_matches if 0 <= rnum <=10000]

>>> in_range
[123, 345, 456, 567, 789]
于 2013-01-23T20:38:27.477 に答える
0

数値以外の文字列がある場合、ソリューションは機能しません。

ValueError:10進数のint()のリテラルが無効です:'abc'

私はこのようなことをします:

mystring = "123 345 456 -123 567 abc 678 789"

mylist = []
for i in mystring.split():
    try:
        ii = int(i)
    except ValueError:
        print "{} is bad".format(i)
    if 0 <= ii <= 10000:
        mylist.append(ii)
    else:
        print  "{} is out of range".format(i)
print mylist

あなたの質問に答えるには:

私。はい、2回以上。

ii。はい、いくつかの例が提供されています。

私の出力は次のようになります。

-123は範囲外です

abcは悪いです

[123、345、456、567、567、678、789]

于 2013-01-23T20:08:54.653 に答える
0

私は議論の熱気を逃したようですが、ここに別の-潜在的に速い-アプローチがあります:

>>> f = lambda(s): set(s) <= set('0123456789 ') and not filter(lambda n: int(n) > 10000, s.split())

テスト:

>>> s1 = '123 345 456 567 678 789'
>>> s2 = '123 345 456 567 678 789 100001'
>>> s3 = '123 345 456 567 678 789 -3'
>>> s4 = '123 345 456 567 678 789 ba'
>>> f(s1)
True
>>> f(s2)
False
>>> f(s3)
False
>>> f(s4)
False

時間を計りませんでしたが、セットの比較でx < 0テスト文字列とのような解析不可能な文字列の両方がすでに処理されているため、他の提案されたソリューションよりも高速である可能性がありますabc。2つのテスト(セット比較と数値範囲)は論理的に結合されているため、最初のテストが失敗すると、2番目のテストを実行できなくなります。

HTH!

于 2013-01-24T08:26:29.133 に答える