2015-05-30 17 views
8

Vì vậy, đối với đầu vào:Thay thế trong chuỗi dựa trên chức năng ouput

accessibility,random good bye 

Tôi muốn đầu ra:

a11y,r4m g2d bye 

Vì vậy, về cơ bản, tôi phải viết tắt tất cả các từ có độ dài lớn hơn hoặc bằng 4 trong các định dạng sau: first_letter + length_of_all_letters_in_between + last_letter

tôi cố gắng để làm điều này:

re.sub(r"([A-Za-z])([A-Za-z]{2,})([A-Za-z])", r"\1" + str(len(r"\2")) + r"\3", s) 

Nhưng nó không hoạt động. Trong JS, tôi sẽ dễ dàng làm:

str.replace(/([A-Za-z])([A-Za-z]{2,})([A-Za-z])/g, function(m, $1, $2, $3){ 
    return $1 + $2.length + $3; 
}); 

Làm thế nào để làm điều tương tự bằng Python?

CHỈNH SỬA: Tôi không thể mất bất kỳ dấu chấm câu nào trong chuỗi gốc.

+2

're' là một chút quá mức cần thiết cho điều này, theo ý kiến ​​của tôi. Tôi chỉ sử dụng 'mystring [0] + str (len (mystring) -2) + mystring [-1]' và 'if' statement để xem khi nào áp dụng này –

+0

@AleksanderLidtke Tôi đã nghĩ về nó nhưng sau đó' mystring 'có những từ riêng biệt (như' khả năng truy cập, tạm biệt, tạm biệt') và không phải là một từ. –

+0

@AleksanderLidtke, còn dấu phẩy thì sao? Làm thế nào để bạn tách các từ? –

Trả lời

3

Vấn đề bạn đang gặp phải là len(r'\2') luôn là 2, không phải là độ dài của nhóm chụp thứ hai trong cụm từ thông dụng của bạn. Bạn có thể sử dụng một biểu lambda để tạo ra một chức năng mà hoạt động giống như mã bạn sẽ sử dụng trong JavaScript:

re.sub(r"([A-Za-z])([A-Za-z]{2,})([A-Za-z])", 
     lambda m: m.group(1) + str(len(m.group(2)) + m.group(3), 
     s) 

Các m tranh luận với lambda là một đối tượng match, và các cuộc gọi đến phương pháp group của nó tương đương với các backreferences bạn đã sử dụng trước đây.

Nó có thể được dễ dàng hơn để chỉ cần sử dụng một mô hình phù hợp từ đơn giản không có nhóm chụp (group() vẫn có thể được gọi mà không có lý lẽ để có được toàn bộ văn bản phù hợp):

re.sub(r'\w{4,}', lambda m: m.group()[0] + str(len(m.group())-2) + m.group()[-1], s) 
+0

Rất ngắn gọn mà tác giả đã sử dụng '[A-Za-z]' trong giải pháp ban đầu của mình và bạn có thể muốn thay đổi giải pháp thay thế của mình thành thay vì '\ w'. – Cu3PO42

+0

Được chấp nhận để đưa ra giải pháp cũng như nêu bật vấn đề của tôi. –

2
tmp, out = "","" 
for ch in s: 
    if ch.isspace() or ch in {",", "."}: 
     out += "{}{}{}{}".format(tmp[0], len(tmp) - 2, tmp[-1], ch) if len(tmp) > 3 else tmp + ch 
     tmp = "" 
    else: 
     tmp += ch 
out += "{}{}{}".format(tmp[0], len(tmp) - 2, tmp[-1]) if len(tmp) > 3 else tmp 
print(out) 

a11y,r4m g2d bye 

Nếu bạn chỉ muốn ký tự alpha sử dụng str.isalpha:

tmp, out = "", "" 
for ch in s: 
    if not ch.isalpha(): 
     out += "{}{}{}{}".format(tmp[0], len(tmp) - 2, tmp[-1], ch) if len(tmp) > 3 else tmp + ch 
     tmp = "" 
    else: 
     tmp += ch 
out += "{}{}{}".format(tmp[0], len(tmp) - 2, tmp[-1]) if len(tmp) > 3 else tmp 
print(out) 
a11y,r4m g2d bye 

Logic là như nhau cho cả hai, nó chỉ là những gì chúng tôi kiểm tra cho rằng khác, nếu not ch.isalpha() là False chúng tôi tìm thấy một ký tự không phải alpha vì vậy chúng ta cần xử lý chuỗi tmp và thêm nó vào chuỗi đầu ra. if len(tmp) không lớn hơn 3 theo yêu cầu, chúng tôi chỉ thêm chuỗi tmp cộng với char hiện tại vào chuỗi ngoài của chúng tôi.

Chúng tôi cần out += "{}{}{} cuối cùng bên ngoài vòng lặp để bắt khi chuỗi không kết thúc bằng dấu phẩy, dấu cách, v.v. Nếu chuỗi kết thúc bằng không phải alpha, chúng tôi sẽ thêm chuỗi trống để không sự khác biệt cho đầu ra.

chọn này sẽ giữ dấu chấm câu và không gian:

s = "accessibility,random good bye !! foobar?" 
def func(s): 
    tmp, out = "", "" 
    for ch in s: 
     if not ch.isalpha(): 
      out += "{}{}{}{}".format(tmp[0], len(tmp) - 2, tmp[-1], ch) if len(tmp) > 3 else tmp + ch 
      tmp = "" 
     else: 
      tmp += ch 
    return "{}{}{}".format(tmp[0], len(tmp) - 2, tmp[-1]) if len(tmp) > 3 else tmp 
print(func(s,3)) 
a11y,r4m g2d bye !! f4r? 
+0

Bạn có thể giải thích logic của mã này không? –

7

gì bạn đang làm trong JavaScript là chắc chắn đúng, bạn đang đi qua một chức năng ẩn danh. Những gì bạn làm trong Python là để vượt qua một biểu thức liên tục ("\ 12 \ 3", vì len(r"\2") được đánh giá trước cuộc gọi hàm), nó không phải là một hàm có thể được đánh giá cho mỗi trận đấu!

Trong khi chức năng ẩn danh bằng Python không phải là khá hữu ích như họ đang có trong JS, họ thực hiện công việc ở đây:

>>> import re 
>>> re.sub(r"([A-Za-z])([A-Za-z]{2,})([A-Za-z])", lambda m: "{}{}{}".format(m.group(1), len(m.group(2)), m.group(3)), "accessability, random good bye") 
'a11y, r4m g2d bye' 

gì xảy ra ở đây là lambda được gọi là cho mỗi thay thế, tham gia một trận đấu vật. Sau đó tôi lấy thông tin cần thiết và xây dựng một chuỗi thay thế từ đó.

+4

@Kasra thế nào?Nó thực hiện chính xác những gì tác giả muốn và là một sự tương tự gần với mã của mình trong JS – Cu3PO42

+0

@Kasra thực sự nó có. Đây là dấu chấm câu hoàn toàn bất khả tri. – Cu3PO42

0

Sử dụng regex và hiểu:

import re 
s = "accessibility,random good bye" 
print "".join(w[0]+str(len(w)-2)+w[-1] if len(w) > 3 else w for w in re.split("(\W)", s)) 

Cung cấp:

a11y,r4m g2d bye 
+0

Điều này sẽ viết tắt bất kỳ ký tự không có từ nào dài hơn bốn ký tự trở lên. Hãy thử 's = 'foo ... bar'' để xem cho chính mình! – Blckknght

+0

@Blckknght, cảm ơn, đã sửa – perreal

-1

Hãy nhìn vào đoạn mã sau

sentence = "accessibility,random good bye" 
sentence = sentence.replace(',', " ") 
sentence_list = sentence.split(" ") 
for item in sentence_list: 
    if len(item) >= 4: 
     print item[0]+str(len(item[1:len(item)-1]))+item[len(item)-1] 

Điều duy nhất bạn nên chăm sóc của dấu phẩy và các ký tự dấu câu khác.

1

Là một cách chính xác thay thế bạn có thể sử dụng chức năng riêng cho re.sub và sử dụng regex đơn giản r"(\b[a-zA-Z]+\b)".

>>> def replacer(x): 
... g=x.group(0) 
... if len(g)>3: 
...  return '{}{}{}'.format(g[0],len(g)-2,g[-1]) 
... else : 
...  return g 
... 
>>> re.sub(r"(\b[a-zA-Z]+\b)", replacer, s) 
'a11y,r4m g2d bye' 

Cũng như một pythonic và chung cách, để có được những lời thay thế trong vòng một danh sách mà bạn có thể sử dụng một danh sách hiểu sử dụng re.finditer:

>>> from operator import sub 
>>> rep=['{}{}{}'.format(i.group(0)[0],abs(sub(*i.span()))-2,i.group(0)[-1]) if len(i.group(0))>3 else i.group(0) for i in re.finditer(r'(\w+)',s)] 
>>> rep 
['a11y', 'r4m', 'g2d', 'bye'] 

Các re.finditer sẽ trả về một máy phát điện có chứa tất cả matchobjects sau đó bạn có thể lặp qua nó và bắt đầu và kết thúc của matchobject s với phương pháp span().

1

Giữ nó đơn giản ...

>>> s = "accessibility,random good bye" 
>>> re.sub(r'\B[A-Za-z]{2,}\B', lambda x: str(len(x.group())), s) 
'a11y,r4m g2d bye' 

\B mà phù hợp giữa hai nhân vật từ hoặc hai ký tự không lời giúp để phù hợp với tất cả các ký tự trừ đầu tiên và cuối cùng.

+0

Tuyệt vời! Không bao giờ nghĩ về điều đó! –

Các vấn đề liên quan