2013-06-04 4 views
16

У меня есть список, который содержит числа и буквы в строковом формате.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) 

Как проверить, что строка может быть преобразована в целое число? Или есть лучший способ сделать это?

ответ

26

Попробуйте это:

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

Из docs:

str.isdigit()

Возвращение верно, если все символы в строке являются цифры, и есть по крайней мере один символ, false в противном случае.

Для 8-битных строк этот метод зависит от локали.


Как было отмечено в комментариях, isdigit() возвращение True не обязательно означает, что строка может быть распознана как междунар с помощью функции int(), и возвращение False не обязательно означает, что она не может быть. Тем не менее, вышеприведенный подход должен работать в вашем случае.

+2

Стоит отметить, что 'str.isdigit()' будет возвращать 'True' на некоторые вещи, которые будут генерировать исключения при передаче через' int() 'и' False' на некоторые вещи, которые не будут. Например: номера надстрочных номеров, «+1». –

+0

@Lattyware Можете ли вы привести пример значений, которые могут вызвать исключение? – satoru

+0

«²» - надстрочный разряд 2. Он возвращает 'True' из' str.isdigit() ', но' int ("²") 'будет вызывать' ValueError'. В обратном порядке '' +1 "' будет синтаксически разбираться, но 'str.isdigit (" + 1 ")' вернет 'False'. –

11

Быстро, просто, но, возможно, не всегда верно:

>>> [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))) 
+0

, но что, если вы хотите игнорировать числа как строки 123', например, в настоящее время вы включаете их – sayth

10

Вы можете использовать исключительную управляемость, как 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'] 
+0

Обратите внимание, что поведение этого отличается от того, что указано OP - OP показал элементы списка, оставшиеся в виде строк. Тем не менее, это, скорее всего, лучший ответ в большинстве случаев. Кроме того, использование 'float()', вероятно, хорошо, но если ассеру нужны только целые целочисленные значения, 'int()' является подходящим. –

3

Обычный способ проверить, может ли что-то быть превращена в int является try его и увидеть, следуя принципу EAFP :

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 

Таким образом, вы можете передать его ex (или кортеж исключений), который вы ожидаете, и те вернут True, но если есть неожиданные исключений, то они будут распространяться. Итак:

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, как это должно быть.

Смежные вопросы