这个问题有更优雅的解决方案吗?

时间:2017-10-27 15:08:13

标签: java

我正在研究一段代码,它针对一堆不同的正则表达式来评估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'会伤到我的眼睛,如果我获得更多关卡,它会变得更糟。所以我的问题是:有更好的方法吗?还是更优雅的解决方案?

编辑:谢谢大家的答案。

4 个答案:

答案 0 :(得分:3)

您可以为通用abstract class创建enumMatcherinterface 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);

    }

所有你真正避免的是以下条件的身体向右缓慢移动。它不一定是最令人愉快的,因为当您阅读代码时很容易错过条件中的副作用。

请注意,这看起来更容易阅读。