我正在研究一段代码,它针对一堆不同的正则表达式来评估String。
正则表达式非常复杂,由产品负责人决定。我基本上必须给出一个更好的分数,取决于String与完美匹配的接近程度。
我现在有3种不同的正则表达式,一种用于完美匹配,一种用于匹配,另一种用于半匹配。我可能会获得更多关卡,这就是为什么我关注当前版本的代码。
我尝试尽可能地简化代码,因此您可以复制并通过它以便在您喜欢的IDE中更好地查看。您无需担心任何这些方法的实现。因为它们已按预期工作,所以我省略了所有这些。
public class MatchEvaluator {
private static final double PERFECT_MATCH = 1.0;
private static final double GOOD_MATCH = .9;
private static final double HALF_MATCH = .5;
private Integer baseScore = 50;
public double evaluate(String searchTerm) {
String suggestion = null;
double score = 0;
boolean isPerfectMatch = false;
Integer searchValue = checkPerfectMatch(searchTerm);
if (searchValue != null) {
score = searchValue * baseScore * PERFECT_MATCH;
suggestion = searchTerm;
isPerfectMatch = true;
} else {
searchValue = checkGoodMatch(searchTerm);
if (searchValue != null) {
score = searchValue * baseScore * GOOD_MATCH;
suggestion = createSuggestion(searchTerm);
} else {
searchValue = checkHalfMatch(searchTerm);
if (searchValue != null) {
score = searchValue * baseScore * HALF_MATCH;
suggestion = createSuggestion(searchTerm);
}
}
}
//Do something with suggestion
//Do something with searchValue
//Do something with isPerfectMatch
return score;
}
private Integer checkHalfMatch(String searchTerm) {
return null;
}
private String createSuggestion(String searchTerm) {
return searchTerm;
}
private Integer checkGoodMatch(String searchTerm) {
return null;
}
private Integer checkPerfectMatch(String searchTerm) {
return null;
}
}
每次看到它们时,那些嵌套的'ifs'会伤到我的眼睛,如果我获得更多关卡,它会变得更糟。所以我的问题是:有更好的方法吗?还是更优雅的解决方案?
编辑:谢谢大家的答案。
答案 0 :(得分:3)
您可以为通用abstract class
创建enum
,Matcher
或interface Matcher {
Integer checkMatch(String searchTerm);
boolean isPerfectMatch();
double getMatchScore();
}
:
null
为您的三个(或可能更多)匹配器实现该接口,封装您已有的三个方法,并实现其他两个方法。现在,您可以将这些匹配器放入列表中,只需迭代列表,直到获得非List<Matcher> matchers = Arrays.asList(
new PerfectScoreMatcher(),
new GoodScoreMatcher(),
new HalfScoreMatcher());
for (Matcher m : matchers) {
Integer searchValue = m.checkMatch(searchTerm);
if (searchValue != null) {
score = searchValue * baseScore * m.getMatchScore();
isPerfectMatch = m.isPerfectMatch();
suggestion = isPerfectMatch ? searchTerm
: createSuggestion(searchTerm);
break;
}
}
分数。
{{1}}
答案 1 :(得分:1)
好吧,你基本上有一个正则表列表,每个都与一个分数相关联。您希望在正则表达式匹配后立即返回分数。您可以创建一个迷你类来保存每个正则表达式和相关分数,然后列出这些并继续处理直到您匹配。像这样:
class RegexScore {
String regex; // I usually make these public in these mini-classes
double score;
}
List<RegexScore> regexList = your regexes in order
boolean match = false;
Iterator<RegexScore> iterator = regexList.iterator();
while (!match && iterator.hasNext()) {
RegexScore regex = iterator.next();
String regex = regexScore.regex;
// evaluate regex, if match, calc score and set match = true to break
// out of loop
}
答案 2 :(得分:1)
如果您定义了一种查找评估结果的特殊方法 - 您可以使用return语句来操作流程。
class EvaluationResult {
double score;
String suggestion;
boolean isPerfectMatch;
public EvaluationResult(double score, String suggestion, boolean isPerfectMatch) {
this.score = score;
this.suggestion = suggestion;
this.isPerfectMatch = isPerfectMatch;
}
}
public EvaluationResult evaluate(String searchTerm) {
Integer searchValue = checkPerfectMatch(searchTerm);
if (searchValue != null) {
return new EvaluationResult(searchValue * baseScore * PERFECT_MATCH, searchTerm, true);
}
searchValue = checkGoodMatch(searchTerm);
if (searchValue != null) {
return new EvaluationResult(searchValue * baseScore * GOOD_MATCH, createSuggestion(searchTerm), false);
}
searchValue = checkHalfMatch(searchTerm);
if (searchValue != null) {
return new EvaluationResult(searchValue * baseScore * HALF_MATCH, createSuggestion(searchTerm), false);
}
return null; //null or null value based on your preference
}
如果您使用的是Java 8+,则可以使用lambda和stream。您还可以减少代码重复。
UPD:java 8版
public EvaluationResult evaluate(String searchTerm) {
return Stream.<Function<String, EvaluationResult>>of(this::checkPerfectMatch, this::checkGoodMatch, this::checkHalfMatch)
.map(f -> f.apply(searchTerm))
.filter(Objects::nonNull)
.findFirst().orElse(null);
}
private EvaluationResult checkPerfectMatch(String searchTerm) {
Integer searchValue = 1; //doStuff
return createEvaluationResult(searchValue, PERFECT_MATCH, searchTerm, true);
}
private EvaluationResult checkGoodMatch(String searchTerm) {
Integer searchValue = 1; //doStuff
return createEvaluationResult(searchValue, GOOD_MATCH, createSuggestion(searchTerm), true);
}
private EvaluationResult checkHalfMatch(String searchTerm) {
Integer searchValue = 1; //doStuff
return createEvaluationResult(searchValue, HALF_MATCH, createSuggestion(searchTerm), true);
}
private EvaluationResult createEvaluationResult(Integer searchValue, double coefficient, String suggestion, boolean isPerfectMatch) {
return searchValue != null
? new EvaluationResult(searchValue * baseScore * coefficient, suggestion, isPerfectMatch)
: null;
}
答案 3 :(得分:1)
最简单的解决方案就是在支票中分配变量:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
所有你真正避免的是以下条件的身体向右缓慢移动。它不一定是最令人愉快的,因为当您阅读代码时很容易错过条件中的副作用。
请注意,这看起来更容易阅读。