Câu hỏi Cách tốt nhất để lấy tiền tố số của một chuỗi


Cách sạch nhất để lấy tiền tố số của một chuỗi trong Python là gì?

Bởi "sạch" tôi có nghĩa là đơn giản, ngắn, dễ đọc. Tôi không thể quan tâm đến hiệu năng, và tôi cho rằng nó hầu như không thể đo lường được bằng Python.

Ví dụ:

Cho chuỗi '123abc456def', cách sạch nhất để lấy chuỗi là gì '123'?

Mã dưới đây có được '123456':

input = '123abc456def'
output = ''.join(c for c in input if c in '0123456789')

Vì vậy, tôi về cơ bản tìm kiếm một số cách để thay thế if với một while.


24
2018-03-08 12:01


gốc


regexp sẽ là một lựa chọn? - MaxU
@ MVU: Tôi đã hy vọng rằng sẽ có một "hoạt động chuỗi" đơn giản mà có thể giúp tôi tiết kiệm gánh nặng của biểu thức chính quy, nhưng nếu bạn nghĩ rằng không có lựa chọn nào khác thì có. - barak manos
Có phải tất cả các tiền tố đều có 3 ký tự hay không? - AlG
@ AIG: Không, nó thay đổi (nếu không, tôi sẽ chỉ sử dụng input[0:3]). - barak manos
@ForceBru: Cảm ơn bạn. Dưới đây là câu trả lời phù hợp hơn với câu hỏi của tôi so với câu trả lời được chấp nhận trong câu hỏi mà bạn đã đề xuất là trùng lặp (tức là câu trả lời dưới đây là "sạch hơn"), vì vậy tôi sẽ chấp nhận câu trả lời ở đây. - barak manos


Các câu trả lời:


Bạn có thể dùng itertools.takewhile sẽ lặp qua chuỗi của bạn (đối số có thể lặp lại) cho đến khi nó gặp mục đầu tiên trả về False (bằng cách chuyển đến hàm dự báo):

>>> from itertools import takewhile
>>> input = '123abc456def'
>>> ''.join(takewhile(str.isdigit, input))
'123'

55
2018-03-08 12:09



Vui lòng bỏ phiếu để mở lại câu hỏi này. Có hai bản sao được đề xuất. Một là một câu hỏi khác (!!!), và câu hỏi khác được đóng bởi chính nó, và ngoài ra, câu trả lời ở đây khớp với câu hỏi của tôi tốt hơn câu trả lời được chấp nhận cho câu hỏi đó (đóng), vì nó giải quyết yêu cầu của tôi giải pháp có thể. Cảm ơn bạn. - barak manos
@barakmanos Tôi chỉ làm điều đó trước khi tôi đọc nhận xét của bạn;) - Kasramvd
Cảm ơn nhiều. Bạn có thể vui lòng xem giải pháp được đề xuất bởi hedgehog @demented dưới đây không? Nó có vẻ rất "sạch", mặc dù tôi ghét phải không chấp nhận câu trả lời của bạn. - barak manos
@barakmanos Tôi để lại một bình luận ở đó. Nó ngắn hơn nhưng không tối ưu về mặt sử dụng bộ nhớ. Nó cũng sử dụng một chỉ mục và hai len chức năng. - Kasramvd
Tôi sẽ upvote bất kỳ giải pháp trông giống như Haskell. Đây chắc chắn là giải pháp "sạch" nhất theo ý kiến ​​của tôi. - ApproachingDarknessFish


Đây là cách đơn giản nhất để trích xuất một danh sách các số từ một chuỗi:

>>> import re
>>> input = '123abc456def'
>>> re.findall('\d+', s)
['123','456']

Nếu bạn cần danh sách int thì bạn có thể sử dụng đoạn mã sau:

   >>> map(int, re.findall('\d+', input ))
   [123,456]

Và bây giờ bạn có thể truy cập phần tử đầu tiên [0] từ danh sách trên


13
2018-03-08 12:10



Đó là một tuyên bố táo bạo. Mặc dù tôi nghĩ đó là một giải pháp tốt. - demented hedgehog
Có lẽ match() sẽ phù hợp hơn, vì OP chỉ cần các chữ số bắt đầu. - Fermi paradox


Phiên bản đơn giản (để lại câu trả lời khác vì có một số cuộc tranh luận thú vị về cách tiếp cận nào tốt hơn)

input[:-len(input.lstrip("0123456789"))]

5
2018-03-08 14:18



Cái này là pythonic;), nhưng như tôi đã nói takewhile() được tối ưu hóa hơn về mặt sử dụng bộ nhớ. - Kasramvd
Điều đó đúng. Tôi sẽ phải mất một cái nhìn thứ hai tại itertools .. Tôi đã không nghe nói về takewhile cho đến bây giờ. - demented hedgehog


input[:len(input) - len(input.lstrip("0123456789"))]

3
2018-03-08 12:59



Đây không phải là một cách tiếp cận tối ưu hóa về mặt sử dụng bộ nhớ (đặc biệt khi bạn đang xử lý các chuỗi lớn hơn). Bởi vì bạn đang tạo một chuỗi bị tước khỏi chuỗi chính và tải nó trong bộ nhớ. - Kasramvd
Vâng. Nó không đặc biệt hiệu quả nhưng bài viết đặc biệt không quan tâm đến hiệu suất và nó là đơn giản và trong thực tế hiệu suất sẽ không thường là vấn đề. Bạn sẽ phải sử dụng dây lớn để chăm sóc. Có phí trên ví dụ trong việc biên dịch các biểu thức thông thường. Nếu bạn thực sự quan tâm về tốc độ làm điều đó trong c. - demented hedgehog
Cũng phụ thuộc vào phần nào của chuỗi là tiền tố .. nếu đó là một triệu chữ số theo sau là "x", cách tiếp cận của bạn cũng sẽ chậm. Có thể nguyên nhân chậm hơn bạn đã có bản sao cũng như một loạt các cuộc gọi chức năng trên không? Tôi muốn được quan tâm để xem so sánh thời gian của hai phương pháp tiếp cận của chúng tôi so với chiều dài chuỗi và độ dài tiền tố. - demented hedgehog


Đây là của tôi đường:

output = input[:next((i for i,v in enumerate(input) if not v.isdigit()),None)]

1
2018-03-08 12:09





Một cách, nhưng không hiệu quả vì nó hoạt động qua toàn bộ chuỗi mà không có break sẽ là:

input_string = '123abc456def'
[input_string[:c] for c in range(len(input_string)) if input_string[:c].isdigit()][-1]

Điều này gắn thêm mỗi chuỗi con với kích thước ngày càng tăng nếu nó là một chữ số và sau đó nối thêm nó. Vì vậy, yếu tố cuối cùng là một trong những bạn tìm kiếm. Bởi vì nó là chuỗi dài nhất vẫn là một chữ số.


1
2018-03-08 12:10





Bạn có thể sử dụng regex

import re
initialNumber = re.match(r'(?P<number>\d+)', yourInput).group('number')

1
2018-03-08 12:23





Một phiên bản regexp khác bỏ đi mọi thứ bắt đầu bằng chữ số đầu tiên:

import re
output = re.sub('\D.*', '', input)

0
2018-03-22 09:39





input = '123abc456def'
output = re.findall(r'^\d+', input)

Sẽ trở lại ['123'] quá.


0
2018-04-10 20:41