4
4

6 回答 6

6

您可以分别定义映射和规则:

public static enum Grade {

    // Letter grades are A, B, C, D, and F
    // Their numeric values are 4, 3, 2, 1, and 0

    A(4),B(3),C(2),D(1),F(0);

    public final double score;

    private Grade(double d) {
        this.score = d;
    }

    // Grades are possibly followed by + or –
    // There is no F+ or F–
    // a + increases the numeric value by 0.3, a – decreases it by 0.3
    // However, an A+ has value 4.0

    public double getModifiedScore(char sign) {
        switch (sign) {
            case '+':
                return score + (score < 4 && score > 0 ? 0.3 : 0);
            case '-':
                return score + (score > 0 ? -0.3 : 0);
            default:
                throw new IllegalArgumentException("Invalid sign");
        }
    }
}

然后只需使用它们(示例假设您已验证输入):

public static double getNumericGrade(String s){
    Grade g = Grade.valueOf(s.substring(0, 1));
    if(s.length() > 1){
        return g.getModifiedScore(s.charAt(1));
    }else {
        return g.score;
    }
}
于 2013-08-25T04:41:57.210 回答
5

我会使用查找表:

private final static Map<String,Double> gradeLookup = 
   new HashMap<String, Double>();

gradeLookup.put("A-", 3.7);

numericValue = gradeLookup.get(grade);

另一个不错的选择是 switch 语句,从 Java 7 开始,它终于可以与字符串一起使用。

这两个选项都为您提供了内置的输入验证,因此用户无法输入诸如“G”或“F+”或“foo”之类的内容。

于 2013-08-25T03:52:56.687 回答
1

使用Map将字符(在本例中为A.. D, F)映射到相应值 ( 4.. 0) 的 a。

当您处理您的输入时:

  • 如果它只有一个字符长,只需在地图中查找字符即可。
  • 如果末尾有+or ,则查找第一个字符并适当处理第二个字符(根据您发布的规则,请记住处理特殊情况,例如)。-A+

你可以尝试这样的事情:

private static final Map<Character, Double> grades = new HashMap<>();
static {
    grades.put('A', 4.0);
    grades.put('B', 3.0);
    grades.put('C', 2.0);
    grades.put('D', 1.0);
    grades.put('F', 0.0);
}

public static double getNumericGrade(String input) {
    if (input == null || input.isEmpty() || input.length() > 2
            || input.matches("F[+-]")
            || !grades.containsKey(input.charAt(0)))  // validate input
        throw new IllegalArgumentException();

    double val = grades.get(input.charAt(0));

    if (input.length() == 1) {
        return val;
    } else if (input.charAt(1) == '+') {
        return (input.charAt(0) == 'A') ? val : val + 0.3;
    } else if (input.charAt(1) == '-') {
        return val - 0.3;
    } else {
        throw new IllegalArgumentException();
    }
}
于 2013-08-25T03:54:23.520 回答
1

一种方法是使用switch- 它适用String于 Java 7。

// Yes, I'm passing grade and shadowing numericValue, since those properties
// aren't used anywhere else in the class.
public double getNumericGrade(String grade) {
    double numericValue = 0;

    switch (grade) {
        case "A+":
        case "A":
            numericValue = 4.0;
            break;
        case "A-":
            numericValue = 3.7;
            break;
        case "B+":
            numericValue = 3.3;
            break;
        case "B":
            numericValue = 3.0;
            break;
        case "B-":
            numericValue = 2.7;
            break;
        case "C+":
            numericValue = 2.3;
            break;
        case "C":
            numericValue = 2.0;
            break;
        case "C-":
            numericValue = 1.7;
            break;
        case "D+":
            numericValue = 1.3;
            break;
        case "D":
            numericValue = 1.0;
            break;
        case "F":
            numericValue = 0;
            break;
        default:
            System.out.println("Letter not in grading system");
            break;
    }
    return numericValue;
}

...但这读起来很冗长。

另一种替代方法是采用我们对数字成绩的规则,并写一些更简洁的东西。

  • 如果等级是某个字母点,它是一个整数(A = 4,B = 3,C = 2,D = 1,F = 0)。
  • 如果等级带有负号,则该值是整数与 0.3 的差。
  • 如果等级带有加号,则该值是整数和 0.3 的总和。

这是一个利用这些规则的解决方案。它可能读起来有点冗长,可能与 switch 没有什么不同,但它是另一种编写方式。

public double getNumericGradeRefactored(String grade) {
    Map<Character, Double> gradeMap = new HashMap<Character, Double>(){{
        put('A', 4.0);
        put('B', 3.0);
        put('C', 2.0);
        put('D', 1.0);
        put('F', 0.0);
    }};

    // split result
    char[] gradeParts = grade.toCharArray();
    double result = gradeMap.get(gradeParts[0]);
    if(gradeParts.length > 1) {
        switch(gradeParts[1]) {
            case '+':
                result += 0.3;
                break;
            case '-':
                result -= 0.3;
                break;
        }
    }
    return result;

}
于 2013-08-25T04:15:58.220 回答
0

我会分别处理“+”或“-”。

检查字母,然后适当地添加或减去包含“+”或“-”的等级值。

编辑:就个人而言,我更喜欢 switch-case 而不是长 if-elseif 语句,但任何一个都可以很好地工作。

于 2013-08-25T03:56:34.483 回答
0

除了@Thilos 关于如何存储实际数据的建议之外,我想补充一点,在这种情况下,您不想同时存储数据的版本Stringint版本,除非性能非常关键。

虽然现在这看起来没什么大不了的,但在许多情况下,您冒着失去它们之间同步的风险,即String说一件事而int说另一件事,因此您会遇到错误。

并且您的构造函数不应该提示输入,除非这变得非常普遍.. 使用String.

于 2013-08-25T04:15:55.257 回答