首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在排序列表元素相等的情况下为它们分配“相同”的竞争位置?

如何在排序列表元素相等的情况下为它们分配“相同”的竞争位置?
EN

Stack Overflow用户
提问于 2018-03-22 17:46:32
回答 3查看 59关注 0票数 1

我有一个运动员名单(姓名、分数、名次),名字和分数已经设定好了。我需要根据比分得到他们在比赛中的名次。

目前,我将它们保存在TreeSet中,因此它们已经按升序排序。如果所有的分数都不同,我可以这样做:

代码语言:javascript
复制
    int place=1;        
    for (Athlete athlete:allAthletes){
        athlete.setRelativePlace(place++);
    }

问题是,如果两个运动员有相同的分数,他们必须有像"1-2“或"8-9-10”这样的分配位置。例如,获胜者都得到了8000分,他们的位置字段中都应该有一个字符串"1-2“。下一个人-如果她的分数是唯一的-将得到正常的"3",等等。有没有办法在几行简单的代码中做到这一点,而不必做两个循环和在运动员类中添加额外的字段?

EN

回答 3

Stack Overflow用户

发布于 2018-03-22 17:55:24

这不是一个完整的答案,但在一次通过所有运动员的过程中生成您想要的排名并不是太难。与其使用8-9-10作为等级标签,我建议对所有三名运动员都使用8。也就是说,有三名运动员并列第八名。

代码语言:javascript
复制
int rank = 0;
int score = -1;

for (Athlete a : allAthletes) {
    int currScore = a.getScore();
    if (currScore != score) {
        ++rank;
        score = currScore;
    }
    a.setRelativePlace(rank);
}

这个排名系统在数据库行话中被称为“密集排名”。使用这种方案,如果有两名运动员并列第一名,三名运动员并列第三名,我们的排名如下:

代码语言:javascript
复制
score | dense rank
100   | 1
100   | 1
95    | 2
80    | 3
80    | 3
80    | 3

编辑:假设你坚持你的需求,然后考虑下面的脚本。我不依赖于你的类,除非我猜出你的代码是什么样子,否则我不能测试它,我只是在一个排序的分数列表上按升序打印排名。

代码语言:javascript
复制
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

票数 1
EN

Stack Overflow用户

发布于 2018-03-22 18:28:44

目前,我将它们保存在TreeSet中,因此它们已经按升序排序。如果你将运动员的得分存储在TreeSet中,TreeSet不会让两个运动员保持相同的分数。

假设relativePlace是整型type.Its,最好将运动员存储在列表中,并用比较器对其进行排序。得分相同的运动员将按插入顺序列出。

代码语言:javascript
复制
 public class Athlete {

     private String name;
     private int score;
     private int relativePlce;
 }

排序将类似于..

代码语言:javascript
复制
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());
票数 0
EN

Stack Overflow用户

发布于 2018-03-22 18:45:59

因为现在只有一个setRelativePlace(int),所以可以存储起始位置:

代码语言:javascript
复制
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);
}

有了一系列地点的数据结构,就可以修补最后找到的地点:

代码语言:javascript
复制
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时:

代码语言:javascript
复制
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);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49425299

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档