2013-01-31 13 views
5

mam listy ciągów znaków w postaci podobnegow Pythonie jak przekonwertować liczbę unosić się w mieszanym listy

a = ['str','5','','4.1'] 

chcę przekonwertować wszystkie numery na liście, aby pływać, ale resztę pozostawić bez zmian, jak to

a = ['str',5,'',4.1] 

próbowałem

map(float,a) 

ale widocznie dał mi jakiś błąd, ponieważ ciąg CA Nie należy konwertować na float. Próbowałem też

a[:] = [float(x) for x in a if x.isdigit()] 

ale to tylko daje mi

[5] 

więc liczba typu float i wszystkie inne struny są tracone. Co powinienem zrobić, aby zachować ciąg i numer w tym samym czasie?

+0

Przepraszam, że nie było to zbyt jasne, lista może być długa i nie znam dokładnej kolejności elementów, co oznacza, że ​​nie wiem, która z nich jest liczbą przed ręką. – LWZ

+0

Czy próbowałeś '' 4.1'.isdigit() 'lub czytając [dokumentację] (http://docs.python.org/2/library/stdtypes.html#str.isdigit)? "Zwraca wartość true, jeśli wszystkie znaki w łańcuchu są cyframi ..." Ponieważ ''.'' nie jest cyfrą, zwraca wartość false. – abarnert

+0

@abarnert, masz rację. Myliłem się co do wersji 4.1 i zostało to naprawione. – LWZ

Odpowiedz

4
for i, x in enumerate(a): 
    try: 
     a[i] = float(x) 
    except ValueError: 
     pass 

Zakłada chcesz zmienić a w miejscu, do tworzenia nowej listy można użyć następujących:

new_a = [] 
for x in a: 
    try: 
     new_a.append(float(x)) 
    except ValueError: 
     new_a.append(x) 

To spróbuj/z wyjątkiem podejście jest standardem EAFP i będzie bardziej wydajny i mniej błąd podatny niż sprawdzanie, czy każdy łańcuch jest prawidłowym zmiennym.

+1

Przykład "jednej linijki" zakończy się niepowodzeniem na "4.1", ponieważ kropka nie jest cyfrą. Zastępując 'if i.isdigit()' poleceniem 'if i.replace ('.', ''). Isdigit()' powinno obejść ten problem. – Valdogg21

+0

Tak, właśnie to sobie uświadomiłem, właśnie usunąłem jedną linijkę, ponieważ napotkasz również problemy z liczbami ujemnymi i notacją naukową. Łatwiej po prostu spróbuj/except. –

7
>>> a = ['str','5','','4.1'] 
>>> a2 = [] 
>>> for s in a: 
...  try: 
...   a2.append(float(s)) 
...  except ValueError: 
...   a2.append(s) 
>>> a2 
['str', 5.0, '', 4.0999999999999996] 

Jeśli robisz matematyki dziesiętny, można zajrzeć do modułu dziesiętnych:

>>> import decimal 
>>> for s in a: 
...  try: 
...   a2.append(decimal.Decimal(s)) 
...  except decimal.InvalidOperation: 
...   a2.append(s) 
>>> a2 
['str', Decimal('5'), '', Decimal('4.1')] 
+0

Dzięki.Ale dlaczego dostaję 4.0999999999999996? Chciałbym mieć taką samą znaczącą cyfrę jak pierwotny numer. – LWZ

+2

@LWZ - tak działają numery zmiennoprzecinkowe. Zobacz [to pytanie] (http://stackoverflow.com/questions/5997027/python-rounding-error-with-float-numbers). – Blair

+2

@LWZ: Ponieważ nie możesz reprezentować '4.1' dokładnie jako' float'. Jest około 69105.00000000000001 pytań na SO o tym, więc szukaj, jeśli potrzebujesz więcej informacji. – abarnert

5

Oto sposób to zrobić bez wyjątkiem obsługi i stosując trochę regex: -

>>> a = ['str','5','','4.1'] 
>>> import re 
>>> [float(x) if re.match("[+-]?(?:\d+(?:\.\d+)?|\.\d+)$", x) else x for x in a] 
4: ['str', 5.0, '', 4.1] 

zauważyć, że ten regex obejmie tylko podstawowy zakres numerów, mający zastosowanie w danym przypadku. Dla bardziej wyszukane regex dopasować szerszy zakres liczb zmiennoprzecinkowych, jak, w tym wykładników, można spojrzeć na to pytanie: -

+0

Czy warto zakotwiczać z '' $ '' w '' re'' '' '\ d + (\. \ D +)? $" '' Dla patologicznych przypadków '3.14pi' itd. Najlepsza odpowiedź nie mniej jednak . – sotapme

+0

@sotapme. Och, tak, masz rację. Dokona edycji. Dzięki :) –

+1

Twoje rozwiązanie nie trafia liczb ujemnych, prawda? Podsumowując, prawie nigdy nie warto używać wyrażeń regularnych, chyba że są one naprawdę wymagane. – Vladimir

3

Moja wersja:

def convert(value): 
    try: 
     return float(value) 
    except ValueError: 
     return value 

map(convert, a) 
Powiązane problemy