Как отсортировать два массива, но держать их в соответствующем порядке? - PullRequest
0 голосов
/ 05 мая 2020

В своей программе я беру список оценок и список имен. Порядок оценок соответствует порядку названий. Я хочу отсортировать оценки от наименьших к высшим или от высших к низшим (не имеет значения), но сохраняю их так, чтобы индексы оценок человека a и человека a были одинаковыми.

Ответы [ 3 ]

0 голосов
/ 05 мая 2020

Во-первых, поскольку вы используете Java, естественным способом сделать это было бы создание класса, например Student, с членами экземпляра класса grade и name. Тогда у вас будет список студентов, которых вы можете отсортировать, что, естественно, сохранит связанные данные вместе.

Однако, если вам нужно придерживаться отдельных списков, уловка состоит в том, чтобы отсортировать список индексов в списке оценок, а не в самом списке оценок. В компараторе вы сравниваете оценки на соответствующих позициях в вашем списке оценок, а не индексы.

List<String> grades = Arrays.asList("F", "A", "C", "D");
List<String> names = Arrays.asList("Tom", "Sue", "Dick", "Harry");

List<Integer> indexes = new ArrayList<>();
for(int i=0; i<grades.size(); i++) indexes.add(i);

indexes.sort((i1, i2) -> grades.get(i1).compareTo(grades.get(i2)));

for(Integer i : indexes)
    System.out.format("%s : %s%n", names.get(i), grades.get(i));

List<String> sortedGrades = new ArrayList<>();
List<String> sortedNames = new ArrayList<>();
for(Integer i : indexes) 
{
    sortedGrades.add(grades.get(i));
    sortedNames.add(names.get(i));
}

System.out.println();
System.out.println(sortedNames);
System.out.println(sortedGrades);

Вывод:

Sue : A
Dick : C
Harry : D
Tom : F

[Sue, Dick, Harry, Tom]
[A, C, D, F]

Просто для сравнения, вот как вы могли бы это сделать это с использованием класса Student:

class Student
{
    String grade;
    String name;
    public Student(String name, String grade)
    {
        this.name = name;
        this.grade = grade;

    }
}

Test:

List<String> grades = Arrays.asList("F", "A", "C", "D");
List<String> names = Arrays.asList("Tom", "Sue", "Dick", "Harry");

List<Student> students = new ArrayList<>();
for(int i=0; i<grades.size(); i++) 
    students.add(new Student(names.get(i), grades.get(i)));

students.sort((s1, s2) -> s1.grade.compareTo(s2.grade));

for(Student s : students)
    System.out.format("%s : %s%n", s.name, s.grade);

Вывод:

Sue : A
Dick : C
Harry : D
Tom : F
0 голосов
/ 05 мая 2020

Объяснение

Возможно, было бы лучше создать объект, представляющий вашего ученика (который будет содержать имя и оценку как атрибуты), вместо того, чтобы пытаться c синхронизировать порядок различных массивов.

Учитывая, что оба ваших массива уже находятся в том же порядке (grades[0] совпадение names[0] и так далее), вам в основном потребуется:

  • итерация одного из ваших массивов для создания ваших учеников list;
  • создать Comparator для сортировки списка в возрастающем порядке или Comparator.reversed () , если вы сортируете его в убывающем порядке;

Пример

Студент. java

package com.stackoverflow;

import java.math.BigDecimal;

public class Student {

    private String name;

    private BigDecimal grade;

    public Student(String name, BigDecimal grade) {
        this.name = name;
        this.grade = grade;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public BigDecimal getGrade() {
        return grade;
    }

    public void setGrade(BigDecimal grade) {
        this.grade = grade;
    }

}

GradeComparator. java

package com.stackoverflow;

import java.util.Comparator;

public class GradeComparator implements Comparator<Student> {

    @Override
    public int compare(Student source, Student target) {
        return source.getGrade().compareTo(target.getGrade());
    }

}

Пример. java

package com.stackoverflow;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class Example {

    public static void main(String[] args) {

        String[] names = {"John", "Mary", "Paul", "Alex"};

        BigDecimal[] grades = {BigDecimal.valueOf(5), BigDecimal.valueOf(3), BigDecimal.valueOf(8), BigDecimal.valueOf(2)};

        List<Student> studentList = new ArrayList<>();

        for (int i = 0; i < names.length; i++) {
            studentList.add(new Student(names[i], grades[i])); // make sure arrays have the same size so you don't get an ArrayOutOfBoundsException
        }

        studentList.sort(new GradeComparator()); // list is now sorted in ascending order

        studentList.sort(new GradeComparator().reversed()); // list is now sorted in descending order

    }

}
0 голосов
/ 05 мая 2020

Вы можете использовать сортировку подсчета с индексом по ключу для этой задачи, время работы алгоритма linear, я предполагаю, что у вас есть не более 2 десятичных знаков после запятой, поэтому я использую Number * 100

 public static void main(String[] args) {
        String[] names = { "Jack", "Sara", "Smith", "Nour", "Salah" };
        double[] degrees = new double[] { 90.0, 98.6, 98.5, 85.6, 100.0 };
        int N = degrees.length;
        int R = 101 * 100;
        int[] count = new int[R + 1];
        double[] aux = new double[N];
        String[] aux2 = new String[N];
        for (int i = 0; i < N; i++) {
            int pos = (int) (degrees[i] * 100) + 1;
            count[pos]++;
        }

        for (int r = 0; r < R; r++)
            count[r + 1] += count[r];

        for (int i = 0; i < N; i++) {
            int pos = (int) (degrees[i] * 100);
            aux[count[pos]] = degrees[i];
            aux2[count[pos]++] = names[i];
        }

        for (int i = 0; i < N; i++) {
            degrees[i] = aux[i];
            names[i] = aux2[i];
        }

        for (int i = 0; i < N; i++) {
            System.out.print(names[i] + ": ");
            System.out.println(degrees[i]);
        }
    }

, вывод

Nour: 85.6
Jack: 90.0
Smith: 98.5
Sara: 98.6
Salah: 100.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...