Tôi không hài lòng với bất kỳ giải pháp nào ở đây. Tôi muốn một giải pháp không quốc tịch. Và tôi không muốn kết thúc trong một vòng lặp vô hạn nếu chuỗi thay thế của tôi đã xảy ra để phù hợp với mô hình. Trong khi tôi ở đó, tôi đã thêm hỗ trợ cho thông số limit
và tham số trả về count
.(Tôi đã sử dụng AtomicInteger
để mô phỏng truyền số nguyên theo tham chiếu.) Tôi đã di chuyển tham số callback
vào cuối danh sách tham số, để dễ dàng xác định một lớp ẩn danh hơn.
Dưới đây là một ví dụ về việc sử dụng:
final Map<String,String> props = new HashMap<String,String>();
props.put("MY_NAME", "Kip");
props.put("DEPT", "R&D");
props.put("BOSS", "Dave");
String subjectString = "Hi my name is ${MY_NAME} and I work in ${DEPT} for ${BOSS}";
String sRegex = "\\$\\{([A-Za-z0-9_]+)\\}";
String replacement = ReplaceCallback.replace(sRegex, subjectString, new ReplaceCallback.Callback() {
public String matchFound(MatchResult match) {
String group1 = match.group(1);
if(group1 != null && props.containsKey(group1))
return props.get(group1);
return match.group();
}
});
System.out.println("replacement: " + replacement);
Và đây là phiên bản của tôi về lớp ReplaceCallback:
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.*;
public class ReplaceCallback
{
public static interface Callback {
/**
* This function is called when a match is made. The string which was matched
* can be obtained via match.group(), and the individual groupings via
* match.group(n).
*/
public String matchFound(MatchResult match);
}
/**
* Replaces with callback, with no limit to the number of replacements.
* Probably what you want most of the time.
*/
public static String replace(String pattern, String subject, Callback callback)
{
return replace(pattern, subject, -1, null, callback);
}
public static String replace(String pattern, String subject, int limit, Callback callback)
{
return replace(pattern, subject, limit, null, callback);
}
/**
* @param regex The regular expression pattern to search on.
* @param subject The string to be replaced.
* @param limit The maximum number of replacements to make. A negative value
* indicates replace all.
* @param count If this is not null, it will be set to the number of
* replacements made.
* @param callback Callback function
*/
public static String replace(String regex, String subject, int limit,
AtomicInteger count, Callback callback)
{
StringBuffer sb = new StringBuffer();
Matcher matcher = Pattern.compile(regex).matcher(subject);
int i;
for(i = 0; (limit < 0 || i < limit) && matcher.find(); i++)
{
String replacement = callback.matchFound(matcher.toMatchResult());
replacement = Matcher.quoteReplacement(replacement); //probably what you want...
matcher.appendReplacement(sb, replacement);
}
matcher.appendTail(sb);
if(count != null)
count.set(i);
return sb.toString();
}
}
Tôi thực sự thích câu trả lời ban đầu của bạn tốt hơn với xếp hàng chuỗi trở lại và lập chỉ mục. Sau đó áp dụng chúng ngược lại. Cách này đơn giản hơn, nhưng dường như làm được nhiều việc hơn, phải quét lại toàn bộ chuỗi cho mỗi trận đấu. Cám ơn vì sự gợi ý! – Mike
Tôi đã thêm đề xuất ban đầu trở lại. Kích thước đầu vào được mong đợi sẽ tạo sự khác biệt về việc lưu lại hoặc xếp hàng sau đó thay thế sẽ hiệu quả hơn. Tôi cho rằng người ta cũng có thể có phương pháp thay thế xếp hàng cho họ, cùng với chuỗi thay thế ... – jdmichal
Errr ... Misspoke. Rõ ràng xếp hàng luôn hiệu quả hơn về thời gian CPU. Sự khác biệt sẽ là liệu đó là một vấn đề đủ lớn để lo lắng. – jdmichal