【问题标题】:Sorting second array accordingly to the indexs of first sorted array根据第一个排序数组的索引对第二个数组进行排序
【发布时间】:2020-11-19 01:18:52
【问题描述】:

我有两个大小相同的数组。

ArrayList<ProfileClass> array1= new ArrayList<>()
ArrayList<Double> array2= new ArrayList<>()

array1 = {b,d,a,c}
数组2 = {2.0,4.0,1.0,3.0}

现在我需要对 array2 进行降序排序。
Collections.sort(array2, Collections.reverseOrder());
Expected result: {4.0,3.0,2.0,1.0}

因此,这些值在针对每个值进行排序之前的索引与排序之后的索引不同。然而,索引是针对 array2 中的每个值更改的,我希望 array1 将针对每个值的索引相应地更改为 array2。

Final Expected result of array1: {d,c,b,a}

【问题讨论】:

  • 你需要使用两个列表,你不能使用Map吗?
  • 是的,我在 array1 中从 Firebase 获取数据,然后在 array2 中进行操作。
  • 难道不能有一个类同时保存两个数组的数据吗?
  • 按类你的意思是数据模型类?

标签: java android arrays sorting


【解决方案1】:

您可以通过将索引(0、1、2、3)按array2 的值排序并将结果映射到array1 的值来获得结果。

System.out.println("array1=" + array1);
System.out.println("array2=" + array2);
ArrayList<ProfileClass> sortedArray1 = IntStream.range(0, array2.size())
    .boxed()
    .sorted(Collections.reverseOrder(Comparator.comparingDouble(i -> array2.get(i))))
    .map(i -> array1.get(i))
    .collect(Collectors.toCollection(ArrayList::new));
System.out.println("sorted array1=" + sortedArray1);

输出:

array1=[b, d, a, c]
array2=[2.0, 4.0, 1.0, 3.0]
sorted array1=[d, c, b, a]

或者你也可以这样做。

ArrayList<ProfileClass> sortedArray1 = IntStream.range(0, array2.size())
    .mapToObj(i -> new Object() {
        double sortKey = array2.get(i);
        ProfileClass value = array1.get(i);
    })
    .sorted(Collections.reverseOrder(Comparator.comparingDouble(obj -> obj.sortKey)))
    .map(obj -> obj.value)
    .collect(Collectors.toCollection(ArrayList::new));

【讨论】:

  • 先生,我有一个问题,如果我有一百万条记录怎么办。会需要很长的时间吗?
  • 你应该这样做并尝试计时。
  • 在我的笔记本电脑上对包含 1000000 个随机双打的列表进行排序只需不到一秒的时间。 List&lt;Double&gt; a = new Random().doubles(1000000).boxed().sorted().collect(Collectors.toList());
  • 非常感谢。您的评论很有帮助。
【解决方案2】:

您应该创建一个临时 Double 数组列表。并且你应该在排序之前保留array2的索引。

预计tmpArrayList = {1, 3, 0, 2}

然后,使用这些索引,您可以重新创建 array1。

如果您不必使用 array1 作为链表,最好array1 = new ProfileList[]; 用于此解决方案。

在这里,我想说,为什么这是必要的,你可以在你的profileclass对象中放另一个字段,例如array2Place??并更新它。我不明白你到底想在这里做什么。比如,array2 的索引是关于 array1 的吗?

【讨论】:

    【解决方案3】:

    使用两个数组创建一个 Map 并使用键(Array 2)从 map 中获取第一个数组(map 值数组 1)。

    //Map it
    Map<Double, ProfileClass> map = IntStream.range(0, array2.size()).boxed()
            .collect(Collectors.toMap(i -> array2.get(i), i -> array1.get(i)));
    Collections.sort(array2, Collections.reverseOrder());
    
    //Create new array for array1
    List<ProfileClass> array11 = new ArrayList<>();
    for (Double d : array2) {
        array11.add(map.get(d));
    }
    
    System.out.println(array11);
    

    【讨论】:

      【解决方案4】:

      假设两个数组(尤其是第一个数组)都可以包含重复项,我建议采用以下解决方案

      ProfileClass[] arr1 = new String[] { b,d,a,c };
      double[] arr2 = new double[] { 2.0,4.0,1.0,3.0 };
      
      List<Tuple<ProfileClass, Double>> list 
        = IntStream.range(0, arr2.length) // create a stream of all possible indexes
        .mapToObj(i -> new Tuple<ProfileClass, Double>(arr1[i], arr2[i])) // zip the two arrays by the index
        .sorted((a,b) -> Double.compare(a.getItem2(), b.getItem2())) // sort the stream according to the second array
        .collect(Collectors.toList());
      
      // write the result back to the array
      for (int i = 0; i < arr1.length; i++) {
        arr1[i] = list.get(i).getItem1();
        arr2[i] = list.get(i).getItem2();
      }
      

      这里的类Tuple定义为:

      public class Tuple<T1, T2> {
        private T1 item1;
        private T2 item2;
      
        public Tuple(T1 item1, T2 item2) {
            this.item1 = item1;
            this.item2 = item2;
        }
      
        public T1 getItem1() { return item1; }
        public T2 getItem2() { return item2; }
      }
      

      【讨论】:

        【解决方案5】:

        如果您能够拥有同时包含两个值的类,则只需要一种。

        如果这是不可能的,请检查@NiravHR 的解决方案,似乎是合法的。

        public class Tester {
        
            static class Holder implements  Comparable<Holder> {
        
                private Holder(String letter, Double value){
                    this.letter = letter;
                    this.value  = value;
                }
        
                String letter;
        
                Double value;
        
                static Holder of(String letter, Double value){
                    return new Holder(letter,value);
                }
        
                @Override
                public int compareTo(Holder o) {
                    return value.compareTo(o.value);
                }
        
                @Override
                public String toString() {
                    return String.valueOf(this.letter);
                }
            }
        
        
            public static void main(String[] args) {
        
               List<Holder> data = Arrays.asList(
                 Holder.of("b",2.0),
                 Holder.of("d",4.0),
                 Holder.of("a",1.0),
                 Holder.of("c",3.0)
               );
               Collections.sort(data, Collections.reverseOrder());
        
        
               System.out.println(data);
            }
        }
        

        【讨论】:

          【解决方案6】:

          简单易用的 TreeMap 快速排序订单。

          TreeMap<Double, ProfileClass> map = new TreeMap<>();
              for (int i = 0; i < array1.size(); i++) {
                  map.put(array2.get(i), array1.get(i));
              }
              final Collection< ProfileClass> sortedArray = map.descendingMap().values();
              System.out.println(sortedArray);
          

          【讨论】:

          • 回答你欣赏的是性能效率不高。 Streams 在程序执行之后执行繁重的操作。对于仅 4 个元素,它总共需要 9 毫秒的时间。试想一下,如果您需要在单个数组中操作 100 或 1000 个元素,它将处理多少时间和内存来为您提供结果。如果您想成为程序员,请考虑并努力。你会意识到明显的不同。您为什么不尝试简单的解决方案而不是繁重的流操作。
          猜你喜欢
          • 1970-01-01
          • 2018-11-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-30
          • 1970-01-01
          • 2016-11-05
          • 1970-01-01
          相关资源
          最近更新 更多