2014-09-02 24 views
7

Giả sử rằng tôi có câu sau đây:Thay thế tất cả các lần xuất hiện của từ cụ thể

bean likes to sell his beans 

và tôi muốn thay thế tất cả các lần xuất hiện của từ cụ thể với các từ khác. Ví dụ: bean đến robertbeans đến cars.

Tôi không thể chỉ sử dụng str.replace vì trong trường hợp này, nó sẽ thay đổi beans thành roberts.

>>> "bean likes to sell his beans".replace("bean","robert") 
'robert likes to sell his roberts' 

Tôi chỉ cần thay đổi toàn bộ các từ, chứ không phải thay đổi từ trong từ khác. Tôi nghĩ rằng tôi có thể đạt được điều này bằng cách sử dụng các biểu thức thông thường nhưng không biết làm thế nào để làm điều đó đúng.

+0

bạn có thể 'chia() 'các văn bản vào từ đầu tiên – cmd

Trả lời

14

Nếu bạn sử dụng regex, bạn có thể xác định ranh giới từ với \b:

import re 

sentence = 'bean likes to sell his beans' 

sentence = re.sub(r'\bbean\b', 'robert', sentence) 
# 'robert likes to sell his beans' 

đây 'đậu' là không thay đổi (để 'roberts') vì 's 'cuối cùng không phải là ranh giới giữa các từ: \b khớp với chuỗi trống, nhưng chỉ chỉ ở đầu hoặc cuối của từ.

Việc thay thế thứ hai cho đầy đủ:

sentence = re.sub(r'\bbeans\b', 'cars', sentence) 
# 'robert likes to sell his cars' 
+1

Tại sao các dấu ngoặc đơn? – Jerry

+1

Tôi cho rằng dấu ngoặc đơn là không cần thiết, chúng chỉ làm cho regex dễ đọc hơn (ít nhất là với tôi). –

+0

Đối với một số lý do, điều này dường như không nhận được tất cả sự xuất hiện của US – Kahless

-1
"bean likes to sell his beans".replace("beans", "cars").replace("bean", "robert") 

Sẽ thay thế tất cả các trường hợp "đậu" bằng "xe hơi" và "đậu" bằng "robert". Điều này làm việc vì .replace() trả về một thể hiện đã sửa đổi của chuỗi gốc. Như vậy, bạn có thể nghĩ về nó theo từng giai đoạn. Nó chủ yếu hoạt động theo cách này:

>>> first_string = "bean likes to sell his beans" 
>>> second_string = first_string.replace("beans", "cars") 
>>> third_string = second_string.replace("bean", "robert") 
>>> print(first_string, second_string, third_string) 

('bean likes to sell his beans', 'bean likes to sell his cars', 
    'robert likes to sell his cars') 
+0

tôi không thể làm theo cách này trong nhiệm vụ thực tế, bởi vì thứ tự này thay thế là undefined – FrozenHeart

3

Nếu bạn thay thế mỗi từ cùng một lúc, bạn có thể thay thế các từ nhiều lần (và không có được những gì bạn muốn). Để tránh điều này, bạn có thể sử dụng một chức năng hoặc lambda:

d = {'bean':'robert', 'beans':'cars'} 
str_in = 'bean likes to sell his beans' 
str_out = re.sub(r'\b(\w+)\b', lambda m:d.get(m.group(1), m.group(1)), str_in) 

Bằng cách đó, một lần bean được thay thế bằng robert, nó sẽ không được sửa đổi một lần nữa (ngay cả khi robert cũng nằm trong danh sách đầu vào từ của mình).

Theo đề xuất của georg, tôi đã chỉnh sửa câu trả lời này với dict.get(key, default_value). giải pháp thay thế (cũng được đề xuất bởi Georg):

str_out = re.sub(r'\b(%s)\b' % '|'.join(d.keys()), lambda m:d.get(m.group(1), m.group(1)), str_in) 
+0

Bạn có thể làm cho đơn giản hơn (và nhanh hơn) và xóa 'if' để trực tiếp tìm trong dict nếu bạn sử dụng' \ bbeans? \ B' cho regex và sử dụng 'm.group (0)' (cho toàn bộ trận đấu) trong lambda. – Jerry

+0

Tôi muốn điều này là đủ chung, vì vậy 1 regex có thể đối phó với bất kỳ văn bản đầu vào + bất kỳ danh sách các từ để thay thế. Vì vậy, tôi không muốn 'đậu' trong regex của tôi. – seb

+0

Tôi hiểu rồi. Nó chỉ là nó sẽ kiểm tra mỗi và mọi từ và tôi tin rằng đó là nút cổ chai chính. – Jerry

-1

tôi biết được một thời gian dài của nó nhưng Điều này trông nhiều hơn nữa thanh lịch? :

reduce(lambda x,y : re.sub('\\b('+y[0]+')\\b',y[1],x) ,[("bean","robert"),("beans","cars")],"bean likes to sell his beans") 
Các vấn đề liên quan