【问题标题】:Sorting based on sort of another array [duplicate]基于另一个数组的排序[重复]
【发布时间】:2019-04-25 09:37:35
【问题描述】:

我有一个字符串数组列表totalValstotalVals 中的每个条目都是一个字符串 name 和一个双精度 loc 在插入数组列表之前连接成一个字符串,例如:

totalVals.add(name + "," + loc);

这就是我获得数据的方式。我已将这些值分成一个字符串和双精度数组,如下所示:

String[] temp;
String[] names = new String[totalVals.size()];
double[] locs = new double[totalVals.size()];

for (int i = 0; i < totalVals.size(); I++){
    temp = totalVals.get(i).splot(",");
    names[i] = temp[0];
    locs[i] = Double.parseDouble(temp[1]);
}

但是,现在我想对数据进行排序并在返回之前将其放回数组列表中。我希望locs 数据按降序排列,我可以使用Arrays.sort(locs, Collections.reverseOrder()); 来做到这一点。但我不知道如何对 names 进行排序,以便名称仍然与它们原来的位置相关联。

totalVals 示例:{"Bahamas,32.2233","Zimbabwe,82.2443","India,56.2355","Australia,24.4363"}

将分为:

names = {"Bahamas","Zimbabwe","India","Australia"};
locs = {32.2233,82.2443,56.2355,24.4363};

然后将被排序到:

names = {"Zimbabwe","India","Bahamas","Australia"};
locs = {82.2443,56.2355,32.2233,24.4363};

那么我将如何对两个数组进行排序,以使两个数组中索引 i 处的关联保持不变?

【问题讨论】:

  • 策略错误。不要拆分成两个数组,而是使用单个对象数组,其中每个对象都有一个名称和一个位置。然后对该数组进行排序。如果设计更好的话,这就是您首先应该收到的,而不是您需要解析的字符串。

标签: java arrays sorting


【解决方案1】:

不要把你的数组变成两个数组,而是把它变成ArrayList&lt;Pair&gt;

Pair 类如下:

public class Pair {
    private String country;
    private int loc;

    public Pair(String country, int loc) {
        this.country = country;
        this.loc = loc;
    }

    // getters and setters here
}

然后像这样对数组进行排序:

Collections.sort(array, Comparator.comparingInt(Pair::getLoc));

然后将你的数组拆分成两个数组。

【讨论】:

    【解决方案2】:

    不是将arraylist分成两个不同的数组并分别排序,而是将ArrayList基于double值降序排序,然后将arraylist分成两个数组

     List<String> list = new ArrayList<>();
        list.add("Bahamas,32.2233");
        list.add("Zimbabwe,82.2443");
        list.add("India,56.2355");
        list.add("Australia,24.4363");
    
       List<String> result = list.stream().sorted((a,b)->b.substring(b.lastIndexOf(",")+1).compareTo(a.substring(a.lastIndexOf(",")+1))).collect(Collectors.toList());
    
     System.out.println(result);  //[Zimbabwe,82.2443, India,56.2355, Bahamas,32.2233, Australia,24.4363]
    

    将列表分解为 double[] 数组和 String[] 数组

    double[] arr = result.stream().mapToDouble(i->Double.parseDouble(i.substring(i.lastIndexOf(",")+1))).toArray();
       System.out.println(Arrays.toString(arr)); // [82.2443, 56.2355, 32.2233, 24.4363]
    
    String[] countries = result.stream().map(i->i.substring(0, i.lastIndexOf(","))).toArray(String[]::new);
       System.out.println(Arrays.toString(countries)); //[Zimbabwe, India, Bahamas, Australia]
    

    Java 8 之前的版本

    通过使用带有自定义比较器的`Collections.sort(),然后将列表拆分为两个不同的数组

     Collections.sort(list, new Comparator<String>() {
    
        @Override
        public int compare(String o1, String o2) {
    
            return o2.substring(o2.lastIndexOf(",")+1).compareTo(o1.substring(o1.lastIndexOf(",")+1));
        }
    });
     System.out.println(list); //[Zimbabwe,82.2443, India,56.2355, Bahamas,32.2233, Australia,24.4363]
    

    【讨论】:

    • 没有 lambda 表达式我该怎么做?我使用的是旧版本的 Java
    • 通过使用自定义比较器更新@tushariyer
    • 随机问题 - 为什么您仍在使用旧版本的 Java? Java 7 已经停产 3 年了,你真的应该更新了。
    【解决方案3】:

    TheWildHealer 的解决方案简洁而优雅。下面是针对旧 Java 平台的类似解决方案,以及用于测试的 main() 方法:

    import java.util.ArrayList;
    import java.util.Collections;
    
    public class LocCountry implements Comparable {
    
        private double loc;
        private String country;
    
        public LocCountry(String country, double loc) {
            this.loc = loc;
            this.country= country;
        }
    
        public double getLoc() {return loc;}
        public String getCountry() {return country;}
    
        public String toString() { return country + " - " + loc;}
        public int compareTo(Object obj2) {
            double loc1 = this.getLoc();
            double loc2 = ((LocCountry)obj2).getLoc();
    
            if (loc1 > loc2) return 1;
            if (loc1 < loc2) return -1;
            return 0;
        }
    
    
        public static void main(String args[]) {
            ArrayList lcs = new ArrayList();
    
            lcs.add(new LocCountry("Bahamas"   , 82.2443));
            lcs.add(new LocCountry("Zimbabwe"  , 56.2355));
            lcs.add(new LocCountry("India"     , 32.2233));
            lcs.add(new LocCountry("Australia" , 24.4363));
            Collections.sort(lcs);
            Collections.reverse(lcs);
    
            for (int i = 0; i < lcs.size(); i++){
                System.out.println(lcs.get(i).toString());
            }
        }
    }
    

    结果:

    Bahamas - 82.2443
    Zimbabwe - 56.2355
    India - 32.2233
    Australia - 24.4363
    

    【讨论】:

      【解决方案4】:

      提供的方法TheWildHealer 肯定比这更干净,但这里有一个不需要自定义类的解决方案。流式传输数组并将其映射到数组/[String, Integer] 对。根据第二个值/整数排序,然后重构为字符串。

      Arrays.stream(totalVals)
          .map(s -> s.split(","))
          .map(ss -> new Object[] {ss[0], Integer.parseInt(ss[1])})
          .sorted(Comparator.comparingInt(ss -> (Integer) ss[1]))
          .map(ss -> ss[0] + "," + ss[1])
          .toArray(String[]::new);
      

      【讨论】:

      • 没有 lambda 表达式我该怎么做?我使用的是旧版本的 Java
      • @tushariyer 这根本不适用于旧版本的 java (JDK
      • @tushariyer 在这种情况下,您肯定需要创建一些类。遵循与@TheWildHealer 相同的风格,但您需要创建一个新的Comparator 类,因为JDK 8 中还引入了方法引用。例如Pair::getLocString[]::new
      • @tushariyer 如果可能的话,您应该尝试让您的团队升级到最新的 JDK 11,或者至少升级到 8。它有很多很酷的好处,而且 JDK 11 保证提供长期支持来自 JDK 开发人员。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-25
      • 2013-06-24
      • 1970-01-01
      • 2021-07-17
      相关资源
      最近更新 更多