我有一个运动员名单(姓名、分数、名次),名字和分数已经设定好了。我需要根据比分得到他们在比赛中的名次。
目前,我将它们保存在TreeSet中,因此它们已经按升序排序。如果所有的分数都不同,我可以这样做:
int place=1;
for (Athlete athlete:allAthletes){
athlete.setRelativePlace(place++);
}问题是,如果两个运动员有相同的分数,他们必须有像"1-2“或"8-9-10”这样的分配位置。例如,获胜者都得到了8000分,他们的位置字段中都应该有一个字符串"1-2“。下一个人-如果她的分数是唯一的-将得到正常的"3",等等。有没有办法在几行简单的代码中做到这一点,而不必做两个循环和在运动员类中添加额外的字段?
发布于 2018-03-22 17:55:24
这不是一个完整的答案,但在一次通过所有运动员的过程中生成您想要的排名并不是太难。与其使用8-9-10作为等级标签,我建议对所有三名运动员都使用8。也就是说,有三名运动员并列第八名。
int rank = 0;
int score = -1;
for (Athlete a : allAthletes) {
int currScore = a.getScore();
if (currScore != score) {
++rank;
score = currScore;
}
a.setRelativePlace(rank);
}这个排名系统在数据库行话中被称为“密集排名”。使用这种方案,如果有两名运动员并列第一名,三名运动员并列第三名,我们的排名如下:
score | dense rank
100 | 1
100 | 1
95 | 2
80 | 3
80 | 3
80 | 3编辑:假设你坚持你的需求,然后考虑下面的脚本。我不依赖于你的类,除非我猜出你的代码是什么样子,否则我不能测试它,我只是在一个排序的分数列表上按升序打印排名。
List<Integer> scores = new ArrayList<>();
scores.add(80);
scores.add(80);
scores.add(80);
scores.add(90);
scores.add(100);
scores.add(100);
Collections.sort(scores);
int pos = 0;
int score = -1;
int prevScore = -1;
int a = 0;
for (int currScore : scores) {
System.out.println("DEBUG: current score is: " + currScore);
if (score == -1) {
score = currScore;
prevScore = currScore;
++a;
continue;
}
if (score != currScore || a == scores.size() - 1) {
String rank = "";
prevScore = score;
// this covers the case of the last score, or group of scores
if (a == scores.size() - 1) ++a;
for (int i=0; i < a - pos; ++i) {
if (i > 0) rank += "-";
rank += (pos + i + 1);
}
for (int i=pos; i < a; ++i) {
System.out.println("Score " + prevScore + " has rank " + rank);
}
score = currScore;
pos = a;
}
++a;
}
Score 80 has rank 1-2-3
Score 80 has rank 1-2-3
Score 80 has rank 1-2-3
Score 90 has rank 4
Score 100 has rank 5-6
Score 100 has rank 5-6点击下面的链接,获得上述代码片段的运行演示。
Demo
发布于 2018-03-22 18:28:44
目前,我将它们保存在TreeSet中,因此它们已经按升序排序。如果你将运动员的得分存储在TreeSet中,TreeSet不会让两个运动员保持相同的分数。
假设relativePlace是整型type.Its,最好将运动员存储在列表中,并用比较器对其进行排序。得分相同的运动员将按插入顺序列出。
public class Athlete {
private String name;
private int score;
private int relativePlce;
}排序将类似于..
athletes.sort((o1, o2) -> new Integer(o1.getScore()).compareTo(o2.getScore()));
int place = 1;
for (Athlete athlete : athletes) {
athlete.setPlcae(place++);
System.out.println( athlete.getName()+":"+athlete.getScore() + ":" + athlete.getPlcae());发布于 2018-03-22 18:45:59
因为现在只有一个setRelativePlace(int),所以可以存储起始位置:
int priorScore = -1;
int priorPlace = -1;
int place = 0;
for (Athlete athlete: allAthletes) {
int score = athlete.getScore();
++place;
if (score != priorScore) {
priorScore = score;
priorPlace = place;
}
athlete.setRelativePlace(priorPlace);
}有了一系列地点的数据结构,就可以修补最后找到的地点:
static class Place {
int start;
int end; // inclusive
@Override
String toString() {
if (start == end) {
return Integer.toString(start);
}
return IntStream.rangeClosed(start, end)
.map(Integer::toString)
.collect(Collectors.joining("-"));
}
}
int priorScore = -1;
Place priorPlace = null;
int place = 0;
for (Athlete athlete: allAthletes) {
int score = athlete.getScore();
++place;
if (score != priorScore) {
priorScore = score;
priorPlace = new Place();
priorPlace.start = place;
}
priorPlace.end = place;
athlete.setRelativePlace(priorPlace);
}当allAthletes是一个排序列表,并且您有两个int字段start和end时:
int priorScore = -1;
int priorPlace = -1;
for (int place = 0; ; ++place) {
if (place == allAthletes.size() || allAthletes.get(place)) {
for (int p = priorPlace; p < place; ++p) {
allAthletes.setTillPlace(place - 1);
}
}
if (place == allAthlets.size()) {
break;
}
int score = athlete.getScore();
if (score != lastScore) {
priorScore = score;
priorPlace = place;
}
athlete.setRelativePlace(priorPlace);
}https://stackoverflow.com/questions/49425299
复制相似问题