英文:
How to sort two arrays but keep them in a corresponding order?
问题
在我的程序中,我会接收一个成绩列表和一个姓名列表。成绩的顺序与姓名的顺序相对应。我想要将成绩从低到高或从高到低(无所谓)进行排序,但要保持人员A的索引和人员A的成绩的对应关系。
英文:
In my program, I take in a list of grades and a list of names. The order of the grades corresponds to the order of the names. I want to sort the grades lowest to highest or highest to lowest (doesn't matter), but keep it so that the index of person a and person a's grade is the same.
答案1
得分: 0
你可以使用基于键索引计数排序(key-indexed counting sort)来完成这个任务,算法的运行时间是线性
的。我假设你的浮点数最多有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
英文:
You can use key-indexed counting sort for this task, the running time of the algorithm is linear
, I assume that you have at most 2 decimal after floating-point so I am using 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]);
}
}
, output
Nour: 85.6
Jack: 90.0
Smith: 98.5
Sara: 98.6
Salah: 100.0
答案2
得分: 0
首先,由于您使用的是Java,处理这个问题的自然方式是创建一个类,例如Student,其中包含成绩和姓名实例成员。然后,您可以拥有一个Student的列表,可以对其进行排序,从而自然地将相关数据保持在一起。
然而,如果您需要继续使用分开的列表,技巧是对成绩列表的索引列表进行排序,而不是对成绩列表本身进行排序。在比较器中,您比较成绩列表中相应位置的成绩,而不是索引。
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;
}
}
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
英文:
Firstly, since you're using Java, the natural way to do this would be to create a class, e.g. Student, with grade and name instance members. You'd then have a list of Students that you could sort, which would naturally keep associated data together.
However, if you need to stick with separate lists, the trick is to sort a list of indexes into the grades list, rather than the grades list itself. In the comparator you compare the grades at the corresponding positions in your grades list, rather than the indices.
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);
Output:
Sue : A
Dick : C
Harry : D
Tom : F
[Sue, Dick, Harry, Tom]
[A, C, D, F]
Just for comparison, here's how you might do it using a Student class:
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);
Output:
Sue : A
Dick : C
Harry : D
Tom : F
答案3
得分: 0
// Explanation
// 创建一个代表学生的对象(其中包含姓名和成绩作为属性),而不是试图同步不同数组的排序顺序。
// 考虑到您的数组已经按相同顺序排列(grades[0] 对应 names[0],依此类推),您基本上需要:
// - 迭代其中一个数组以创建学生列表;
// - 创建一个 [Comparator](https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html) 以升序排序列表,
// 或者创建一个 [Comparator.reversed()](https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#reversed--)
// 以降序排序列表;
// Example
/** Student.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());
}
}
/** Example.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
}
}
英文:
Explanation
It might be a better idea to create an object to represent your Student (which will contain name and grade as attributes) instead of trying to sync the ordering of different arrays.
Considering both your arrays are already in the same order (grades[0]
match names[0]
and so on) you will basically need to:
- iterate one of your arrays to create your Students list;
- create a Comparator to sort your list in ascending order or a Comparator.reversed() if you to sort it in descending order;
Example
Student.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());
}
}
Example.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
}
}
专注分享java语言的经验与见解,让所有开发者获益!
评论