2013-01-31 45 views
5

Tôi có một danh sách các chuỗi trong các hình thức nhưbằng Python làm thế nào để chuyển đổi số nổi trong một danh sách hỗn hợp

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

Tôi muốn chuyển đổi tất cả các số trong danh sách thả nổi, nhưng để lại phần còn lại không thay đổi, như thế này

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

tôi đã cố gắng

map(float,a) 

nhưng dường như nó đã cho tôi một lỗi bởi vì một số chuỗi ca nnot được chuyển thành float. Tôi cũng đã cố gắng

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

nhưng nó chỉ mang lại cho tôi

[5] 

nên số float và tất cả các chuỗi khác bị mất. Tôi nên làm gì để giữ chuỗi và số cùng một lúc?

+0

Xin lỗi tôi đã không rõ ràng, danh sách có thể dài và tôi không biết thứ tự chính xác của các yếu tố, có nghĩa là tôi không biết cái nào là số trước khi bàn tay. – LWZ

+0

Bạn đã thử làm '' 4.1'.isdigit() ', hoặc đọc [tài liệu] (http://docs.python.org/2/library/stdtypes.html#str.isdigit)? "Trả về true nếu tất cả các ký tự trong chuỗi là chữ số ..." Vì ''.'' không phải là một chữ số, nó trả về false. – abarnert

+0

@abarnert, bạn nói đúng. Tôi đã sai về 4.1 và bây giờ nó đã được sửa. – LWZ

Trả lời

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

này giả định bạn muốn thay đổi a tại chỗ, để tạo một danh sách mới, bạn có thể sử dụng như sau:

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

này thử/trừ phương pháp là tiêu chuẩn EAFP và sẽ hiệu quả hơn và ít dễ bị lỗi hơn kiểm tra xem liệu mỗi chuỗi có phải là một phao hợp lệ hay không.

+1

Ví dụ một lớp sẽ thất bại trên '4.1' vì ký tự dấu chấm không phải là một chữ số. Thay thế 'if i.isdigit()' bằng 'if i.replace ('.', ''). Isdigit()' sẽ giải quyết vấn đề đó. – Valdogg21

+0

Vâng, tôi chỉ nhận ra rằng, tôi vừa loại bỏ một lớp lót vì bạn cũng sẽ gặp phải các vấn đề với số âm và ký pháp khoa học. Dễ dàng hơn để thực hiện thử/ngoại trừ. –

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] 

Nếu bạn đang làm toán số thập phân, bạn có thể muốn xem xét các mô-đun số thập phân:

>>> 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

Cảm ơn.Nhưng tại sao tôi lại nhận được 4.0999999999999996? Tôi muốn có con số đáng kể giống như con số ban đầu. – LWZ

+2

@LWZ - đó là cách các số điểm nổi hoạt động. Xem [câu hỏi này] (http://stackoverflow.com/questions/5997027/python-rounding-error-with-float-numbers). – Blair

+2

@LWZ: Bởi vì bạn không thể đại diện cho '4.1' chính xác như một 'phao'. Có khoảng 69105.00000000000001 câu hỏi về SO về điều này, do đó, tìm kiếm nếu bạn cần thêm thông tin. – abarnert

5

Đây là một cách để làm điều đó mà không xử lýngoại lệ và sử dụng một chút 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] 

Lưu ý rằng, regex này sẽ chỉ bao gồm một phạm vi cơ bản của con số, áp dụng trong trường hợp của bạn. Đối với regex phức tạp hơn để phù hợp với một phạm vi rộng lớn hơn của số dấu chấm động, như thế nào, bao gồm cả mũ, bạn có thể có một cái nhìn tại câu hỏi này: -

+0

Có đáng để neo với '' $ '' trong '' re'' '' "\ d + (\. \ D +)? $" '' Cho các trường hợp bệnh lý '3.14pi' vv. Câu trả lời hay nhất không kém . – sotapme

+0

@sotapme. Ồ vâng, bạn nói đúng. Sẽ chỉnh sửa nó. Cảm ơn :) –

+1

Giải pháp của bạn bỏ lỡ số âm, phải không? Tất cả trong tất cả, nó gần như không bao giờ là một ý tưởng tốt để sử dụng regexps trừ khi họ đang thực sự cần thiết. – Vladimir

3

phiên bản của tôi:

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

map(convert, a) 
Các vấn đề liên quan