Đúc số nguyên tổng quát trong Python


8

Lý lịch

Tôi có một chuỗi trong Python mà tôi muốn chuyển đổi thành một số nguyên. Thông thường, tôi sẽ chỉ sử dụng int:

>>> int("123")
123

Thật không may, phương pháp này không mạnh mẽ lắm, vì nó chỉ chấp nhận các chuỗi khớp -?[0-9]+(sau khi xóa bất kỳ khoảng trắng hàng đầu hoặc dấu). Ví dụ: nó không thể xử lý đầu vào có dấu thập phân:

>>> int("123.45")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '123.45'

Và nó chắc chắn không thể xử lý điều này:

>>> int("123abc?!")

Mặt khác, chính xác hành vi này có thể có mà không có bất kỳ phiền phức nào trong Perl, PHP và thậm chí cả QBasic khiêm tốn:

INT(VAL("123abc"))   ' 123

Câu hỏi

Đây là nỗ lực ngắn nhất của tôi tại "tổng quát int" này trong Python. Đó là 50 byte, giả sử rằng chuỗi gốc nằm trong svà kết quả sẽ kết thúc bằng i:

n="";i=0
for c in s:
 n+=c
 try:i=int(n)
 except:0

Khá đơn giản, nhưng try/ exceptbit là xấu và dài. Có cách nào để rút ngắn nó?

Chi tiết

Câu trả lời cần phải làm tất cả những điều sau đây:

  • Bắt đầu với một chuỗi trong s; kết thúc với giá trị nguyên của nó trong i.
  • Số nguyên là lần chạy đầu tiên của các chữ số trong chuỗi. Tất cả mọi thứ sau đó được bỏ qua, bao gồm các chữ số khác nếu chúng đến sau các chữ số không.
  • Các số 0 đứng đầu trong đầu vào là hợp lệ.
  • Bất kỳ chuỗi nào không bắt đầu bằng một số nguyên hợp lệ có giá trị là 0.

Các tính năng sau được ưa thích , mặc dù không bắt buộc:

  • Một -dấu hiệu duy nhất ngay trước các chữ số làm cho số nguyên âm.
  • Bỏ qua khoảng trắng trước và sau số.
  • Hoạt động tốt như nhau trong Python 2 hoặc 3.

(Lưu ý: mã của tôi ở trên đáp ứng tất cả các tiêu chí này.)

Các trường hợp thử nghiệm

"0123"   -> 123
"123abc" -> 123
"123.45" -> 123
"abc123" -> 0
"-123"   -> -123 (or 0 if negatives not handled)
"-1-2"   -> -1 (or 0 if negatives not handled)
"--1"    -> 0
""       -> 0

Một số thứ liên quan: codegolf.stackexchange.com/questions/28783/ (nhưng ở đó đã tuyên bố rõ ràng rằng đầu vào sẽ là các số nguyên được hình thành đúng).
DLosc

1
Nên "12abc3"cho cái gì?
orlp

@orlp 12- tương tự như "123.45"trường hợp.
DLosc

(lambda(x)(or(parse-integer x :junk-allowed t)0))(Lisp chung, 49 byte) - Chỉ được đăng dưới dạng nhận xét vì được tích hợp sẵn.
coredump

1
@coredump :junk-allowed--ha, thật tuyệt! Tôi sẽ làm cho điều này trở thành một thách thức golf chung, vì nó không phải là thực tế rằng câu trả lời trong nhiều ngôn ngữ là tầm thường. Nhưng cảm ơn vì Lisp. : ^)
DLosc

Câu trả lời:


4

40 byte

import re;i=int("0"+re.split("\D",s)[0])

và bạn có thể làm phủ định cho 8 ký tự nữa:

import re;i=int((re.findall("^-?\d+",s)+[0])[0])

@DLosc Ah bạn nói đúng, đã không kiểm tra cái thứ hai đủ rõ ràng. Khoảnh khắc 'aha' là khi tôi nhận ra một số hàm regex python trả về chuỗi không phải MatchObjects
KSab

1
import re;i=int((re.findall("^-?\d+",s)+[0])[0])hoạt động, cho 48 byte.
DLosc

6

Con trăn 2, 47 , 46

Nó không ngắn như sử dụng regex, nhưng tôi nghĩ nó tối nghĩa.

i=int(('0%sx'%s)[:~len(s.lstrip(str(1<<68)))])

-1 do KSab - strvới một số nguyên lớn hoạt động tốt hơn toán tử repr vì nó không đặt dấu Lchấm hết.


2
bạn có thể tắt một byte bằng cách sử dụng str(1<<68)bên trong lstrip
KSab

Ồ Giải trí tối nghĩa là đúng! (Điều này chỉ xử lý các số không âm, đúng không?)
DLosc

Một phần thưởng khác của đề xuất của @ KSab là khả năng tương thích Python 3.
DLosc
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.