2009-11-07 234 views
0

我有两个学生对象。比较对象

class Student{ 
int physics; 
int english; 
int chemistry; 
} 

我需要比较每个科目的学生A分数和所有科目的学生B分数。

物理学中的标记需要与物理学,英语,化学中的B标记进行比较。 同样,一个英语与所有三个B.

如果有ATLEAST一个比赛说A的化学标记等于B的英文标记,然后 停止执行,并返回假的。

我的逻辑是

if(a.getPhysics==b.getPhysics || a.getPhysics==b.getEnglish || a.phy==b.chem || ...){ 
    return false; 
} 

这是好还是什么其他好的逻辑??????

回答

1

那么,在任何情况下你都必须做出O(n^2)的比较,问题是代码是多么干净。

你现在建议的是6个布尔比较好,如果你有30个主题?你会保持你需要做的比较吗?

保持简单,我宁愿保持成绩的ListMap,然后做一个嵌套的迭代:

for (int gradeA : thisStudent.getGrades()) { 
    for (int gradeB : otherStudent.getGrades()) { 
     if (gradeA == gradeB) return false; 
    } 
} 
return true; 

当然需要这个代码能够适应您的情况(首不同的迭代对比地图,通过每次不检查每个等级进行优化,从中提取出一种方法等等)

1

稍微改进一下就是在Student类中创建一个方法来完成它。

1

这些属性(课程物理,英语,...)不应该在Student类。一个更好的选择是创建一个CourseModel,在那里你存储所有课程,并跟踪所有参加课程的Student。从CourseModel开始,您可以查询特定的Student并获取所有课程(作为数组/集合)。当你有两个集合/数组时,只需创建一个嵌套的for-statement来比较它们。

1

使用HashSets:

Set<Integer> aMarks = new HashSet<Integer>(); 
Set<Integer> bMarks = new HashSet<Integer>(); 

Collections.addAll(aMarks, 2, 3, 9); 
Collections.addAll(bMarks, 4, 2, 2); 

boolean check = Collections.disjoint(aMarks, bMarks); 
return check; 

为不用测试。您可以更改Collections.addAll(...)用新的方法Student.getMarksAsSet()

+0

除了另一个数据结构之外,您还需要在集合中保存分数,因为您会丢失哪个分数是哪个主题的粒度。 – 2009-11-07 11:10:09

+0

但不幸的是,我无法更改学生对象。它在一个罐子里。 – crazyTechie 2009-11-07 11:17:14

+0

如果你不能更改Student类,请逐个添加你的标记:'aMarks.add(a.getPhysics)','aMarks.add(a.getEnglish)'...... – 2009-11-07 11:24:10

1

您可以添加的能力Student返回其标记为一组:

public class Student { 
    private int physics; 
    private int english; 
    private int chemistry; 

    public Student(int physics, int english, int chemistry) { 
     this.physics = physics; 
     this.english = english; 
     this.chemistry = chemistry; 
    } 

    public Set<Integer> marks() { 
     return new HashSet<Integer>(Arrays.asList(physics, english, chemistry)); 
    } 
} 

然后,当试图确定两个学生匹配,所有你需要看到的是他们的两个标志各自的集合是否相交,如StudentMatcher做:

public class StudentMatcher { 
    public boolean matches(Student student1, Student student2) { 
     Set<Integer> studentMarks1 = student1.marks(); 
     Set<Integer> studentMarks2 = student2.marks(); 
     return haveIntersection(studentMarks1, studentMarks2); 
    } 

    private boolean haveIntersection(Set<Integer> studentMarks1, Set<Integer> studentMarks2) { 
     return studentMarks1.removeAll(studentMarks2); 
    } 
} 

这里是一个单元测试来验证它的工作原理:

public class StudentMatcherTest { 
    @Test 
    public void matches() { 
     StudentMatcher matcher = new StudentMatcher(); 
     Student student1 = new Student(34, 45, 66); 
     Student student2 = new Student(99, 55, 34); 
     Student student3 = new Student(11, 22, 33); 

     assertTrue("Should match", matcher.matches(student1, student2)); 
     assertFalse("Should not match", matcher.matches(student1, student3)); 
    } 
} 

还有更多的事情可以做到这一点,但我假设你的代码比你发布的代码更复杂,所以希望这足以让你走上更好的道路。

0

如果标记的范围很小(AF而非百分比),并且您需要比较多个主题中的标记而不是您给出的三个标记,则填充一组布尔值以确定第一个学生是否具有给定的标记,然后检查数组是否有值。那将是O(N + M),其中N是主题的数量,M是可能的等级的数量。

如果你只有三个主题,硬编码测试并没有那么糟糕 - 你需要六行来获得每个标记。