Java - Sort one array based on values of another array?

后端 未结 10 1749
不思量自难忘°
不思量自难忘° 2020-11-30 12:02

I have an array of Strings that are instances of a class from external code that I would rather not change.

I also have an array of ints that was generated by callin

相关标签:
10条回答
  • 2020-11-30 12:18

    If you're constructing array B only to be used for this sorting, you can defer calculating it's values within A's compareTo(). In other words, calculate weights of strings only in comparisons during sorting.

    0 讨论(0)
  • 2020-11-30 12:19

    Maybe not exactly for that case, but for those who looking for answer how to sort one array of String based on another:

    // Array of values, in a order of sorting
    static final Map<String, Integer> ROUNDS_SORT = new HashMap<String, Integer>();
    static {
        ROUNDS_SORT.put("f", 0);
        ROUNDS_SORT.put("s", 1);
        ROUNDS_SORT.put("q", 2);
        ROUNDS_SORT.put("r16", 3);
        ROUNDS_SORT.put("r32", 4);
        ROUNDS_SORT.put("r64", 5);
    }
    
    // Your array to be sorted
    static ArrayList<String> rounds = new ArrayList<String>() {{
        add("f");
        add("q");
        add("q");
        add("r16");
        add("f");
    }};
    
    // implement
    public List<String> getRoundsSorted() {
        Collections.sort(rounds, new Comparator<String>() {
            @Override
            public int compare(String p1, String p2) {
                return Integer.valueOf(ROUNDS_SORT.get(p1)).compareTo(Integer.valueOf(ROUNDS_SORT.get(p2)));
            }
        });
        return rounds;
    }
    
    0 讨论(0)
  • 2020-11-30 12:20

    I solved this problem by using Comparator interface.

     import java.util.Comparator;
     import java.util.Collections;
     import java.util.List;
     import java.util.Arrays;
    
    
     public class ComparatorDemo {
    
     public static void main(String[] args) {
        List<Area> metaData = Arrays.asList(
                new Area("Joe", 24),
                new Area("Pete", 18),
                new Area("Chris", 21),
                new Area("Rose",21)
        );
    
        Collections.sort(metaData, new ResultComparator());
        for(int i =0 ;metaData.size()>i;i++)
                 System.out.println(metaData.get(i).output);
    
    
      }
     }
    
    
     class ResultComparator implements Comparator<Area> {
         @Override
         public int compare(Area a, Area b) {
             return a.result < b.result ? -1 : a.result == b.result ? 0 : 1;
         }
     }
    
     class Area{
       String output;
       int result;
    
    Area(String n, int a) {
        output = n;
        result = a;
         }
     }
    
    0 讨论(0)
  • 2020-11-30 12:24

    I had a similar problem, and solved it by coding a sorting algorithm which sorted an array of measures, and made identical swaps in the array of objects. Here is the code, with tests, best wishes and no promises:

    package other;
    
    import java.util.Arrays;
    import java.util.Random;
    
    /**
     * Sorts an array of objects (<code>bags</code>) by a separate array of doubles (<code>measures</code>). 
     * It sorts into ascending order. 
     * <p>
     * The <code>results</code> array is always a new array. 
     * <p>
     * The algorithm used:<ul>
     * <li> Is (I believe) a merge-sort, which would mean it is stable. (I haven't tested this.)
     * <li> Efficiently exploits already ordered subsequences. 
     * <li> Requires the allocation of eight arrays: four of the baggage type, four of doubles, each the length of the original data. 
     * </ul>
     * <p>
     * A <code>NaN</code> in the <code>measures</code> - I haven't thought about that, and don't want to. 
     * <p>
     * There is test code at the end of the class. 
     */
    public class SortBaggageByDouble { 
    
        public final Object [] results ; 
    
        protected final int length ; 
    
        public SortBaggageByDouble(Object[] bags, double[] measures) { 
            this.length = bags.length; 
            if (bags.length!=measures.length) throw new IllegalArgumentException("Mismatched lengths: payload array "+bags.length+", measures array "+measures.length); 
            this.results = new Object[length]; 
            Object [] bagsA = new Object[length] ; 
            Object [] bagsB = new Object[length] ; 
            Object [] bagsC = new Object[length] ; 
            Object [] bagsD = new Object[length] ; 
            double [] measuresA = new double[length] ; 
            double [] measuresB = new double[length] ; 
            double [] measuresC = new double[length] ; 
            double [] measuresD = new double[length] ; 
            System.arraycopy(bags, 0, bagsA, 0, length); 
            System.arraycopy(measures, 0, measuresA, 0, length); 
            munge(length, 0, bagsA, bagsB, bagsC, bagsD, measuresA, measuresB, measuresC, measuresD); 
        }
    
        private void munge(int inLengthA, int inLengthB, Object[] inBagsA, Object[] inBagsB, Object[] outBagsC, Object[] outBagsD, double[] inMeasuresA, double[] inMeasuresB, double[] outMeasuresC, double[] outMeasuresD) { 
            int outLengthC = 0 ; 
            int outLengthD = 0 ; 
            int cursorA = 0 ; 
            int cursorB = 0 ; 
            boolean toC = true ; 
            while(outLengthC+outLengthD<length) { 
                boolean fromA ; 
                if (cursorA>=inLengthA) { 
                    fromA = false ; 
                } else if (cursorB>=inLengthB) { 
                    fromA = true ; 
                } else { 
                    fromA = inMeasuresA[cursorA] <= inMeasuresB[cursorB] ;  
                } 
                double tmpMeasure = fromA ? inMeasuresA[cursorA] : inMeasuresB[cursorB] ; 
                Object tmpBag = fromA ? inBagsA[cursorA] : inBagsB[cursorB] ; 
                if (fromA) cursorA ++ ; else cursorB ++ ; 
                if (toC) { 
                    if (outLengthC==0 || (outMeasuresC[outLengthC-1]<=tmpMeasure)) { 
                        outMeasuresC[outLengthC] = tmpMeasure ; 
                        outBagsC[outLengthC] = tmpBag ; 
                        outLengthC ++ ; 
                    } else { 
                        toC = false ; 
                        outMeasuresD[outLengthD] = tmpMeasure ; 
                        outBagsD[outLengthD] = tmpBag ; 
                        outLengthD ++ ; 
                    }
                } else { 
                    if (outLengthD==0 || (outMeasuresD[outLengthD-1]<=tmpMeasure)) { 
                        outMeasuresD[outLengthD] = tmpMeasure ; 
                        outBagsD[outLengthD] = tmpBag ; 
                        outLengthD ++ ; 
                    } else { 
                        toC = true ; 
                        outMeasuresC[outLengthC] = tmpMeasure ; 
                        outBagsC[outLengthC] = tmpBag ; 
                        outLengthC ++ ; 
                    }
                }
            }
            if (outLengthC==length) { 
                System.arraycopy(outBagsC, 0, results, 0, length); 
            } else { 
                munge(outLengthC, outLengthD, outBagsC, outBagsD, inBagsA, inBagsB, outMeasuresC, outMeasuresD, inMeasuresA, inMeasuresB); 
            }
        }
    
        /**
         * Subclass to sort strings, with a result object <code>sortedStrings</code> which is of a useful type. 
         */
        public static class Strings extends SortBaggageByDouble { 
    
            public final String [] sortedStrings ; 
    
            public Strings(String[] in, double[] measures) {
                super(in, measures);
                this.sortedStrings = new String[results.length]; 
                for (int i=0 ; i<results.length ; i++) sortedStrings[i] = (String) results[i] ; 
            } 
    
        }
    
        /**
         * Tests sorting - assumes there are no duplicates among the measures. 
         */
        private static class NoDuplicatesTest { 
            private NoDuplicatesTest(String[] shuffledStrings, double[] shuffledMeasures, String[] expectedStrings) { 
                SortBaggageByDouble.Strings sorter = new SortBaggageByDouble.Strings(shuffledStrings, shuffledMeasures); 
                if (!Arrays.equals(expectedStrings, sorter.sortedStrings)) throw new RuntimeException("Test failed"); 
            }
        }
    
        private static class MultiseedNoDuplicatesTest { 
            private MultiseedNoDuplicatesTest(String[] orderedStrings, double[] orderedMeasures, int[] seeds) { 
                int length = orderedStrings.length;
                for (int seed : seeds) { 
                    Random random = new Random(seed); 
                    int [] shuffleIndices = new int[length] ; 
                    for (int i=0 ; i<length ; i++) shuffleIndices[i] = i ; 
                    for (int i=1 ; i<length ; i++) { 
                        int j = random.nextInt(i+1); // 'j' is in the range 0..i, bounds inclusive. 
                        int tmp = shuffleIndices[i]; 
                        shuffleIndices[i] = shuffleIndices[j] ; 
                        shuffleIndices[j] = tmp ; 
                    }
                    String[] shuffledStrings = new String[length]; 
                    double[] shuffledMeasures = new double[length]; 
                    for (int i=0 ; i<length ; i++) { 
                        shuffledStrings[shuffleIndices[i]] = orderedStrings[i] ; 
                        shuffledMeasures[shuffleIndices[i]] = orderedMeasures[i] ; 
                    }
                    if (false && 0<length && length<8) { 
                        System.out.println("shuffleIndices is "+ stringfor(shuffleIndices)); 
                        System.out.println("shuffledStrings is "+ stringfor(shuffledStrings)); 
                        System.out.println("shuffledMeasures is "+ stringfor(shuffledMeasures)); 
                    }
                    new NoDuplicatesTest(shuffledStrings, shuffledMeasures, orderedStrings); 
                }
            }
        }
    
        private static class MultilengthMultiseedNoDuplicatesTest { 
            MultilengthMultiseedNoDuplicatesTest(int[] lengths, int[] seeds) { 
                for (int i=0 ; i<lengths.length ; i++) { 
                    int length = lengths[i] ; 
                    String[] orderedStrings = new String[length] ; 
                    double[] orderedMeasures = new double[length] ; 
                    for (int j=0 ; j<length ; j++) { 
                        orderedStrings[j] = "_"+j+"_" ; 
                        orderedMeasures[j] = j ; 
                    }
                    if (false && 0<length && length<8) { 
                        System.out.println("orderedStrings is "+ stringfor(orderedStrings)); 
                        System.out.println("orderedMeasures is "+ stringfor(orderedMeasures)); 
                    }
                    new MultiseedNoDuplicatesTest(orderedStrings, orderedMeasures, seeds); 
                }
    
            }
        }
    
        public static class ClassTest { 
            ClassTest() { 
                new MultilengthMultiseedNoDuplicatesTest(new int[]{0}, new int[]{8543, 45125}); 
                new MultilengthMultiseedNoDuplicatesTest(new int[]{1}, new int[]{8543, 45125}); 
                new MultilengthMultiseedNoDuplicatesTest(new int[]{2}, new int[]{8543, 45125, 4545, 785413}); 
                new MultilengthMultiseedNoDuplicatesTest(new int[]{3, 4, 5, 6, 7, 8, 9, 10}, new int[]{8543, 45125, 4545, 785413}); 
                new MultilengthMultiseedNoDuplicatesTest(new int[]{50, 100, 1000}, new int[]{474854, 43233}); 
                //////  Passed! Bye bye.  
                System.out.println("Passed test suite "+this.getClass().getCanonicalName()); 
            }
        }
    
        public static String stringfor(int[] array) {
            StringBuilder sb = new StringBuilder(); 
            build(sb, array);
            return sb.toString();
        }
    
        public static void build(StringBuilder sb, int[] array) { 
            for (int i=0 ; i<array.length ; i++) { 
                if (sb.length()>0) sb.append(' '); 
                sb.append(array[i]); 
            } 
        }
    
        public static String stringfor(double[] array) {
            StringBuilder sb = new StringBuilder(); 
            build(sb, array);
            return sb.toString();
        }
    
        public static void build(StringBuilder sb, double[] array) { 
            for (int i=0 ; i<array.length ; i++) { 
                if (sb.length()>0) sb.append(' '); 
                sb.append(array[i]); 
            } 
        }
    
        public static String stringfor(String[] labels) {
            StringBuffer sb = new StringBuffer();
            String sep = "" ; 
            for (int i=0 ; i<labels.length ; i++) { 
                sb.append(sep); 
                String label = labels[i] ; 
                sb.append(label!=null ? label : "null"); 
                sep = ", " ; 
            }
            return sb.toString();
        }
    
    }
    
    0 讨论(0)
  • 2020-11-30 12:28

    In java 8, you can do this

    with a lambda:

        String[] strings = new String[]{"string1", "string2", "string3"};
        final int[] ints = new int[]{40, 32, 34};
    
        final List<String> stringListCopy = Arrays.asList(strings);
        ArrayList<String> sortedList = new ArrayList(stringListCopy);
        Collections.sort(sortedList, (left, right) -> ints[stringListCopy.indexOf(left)] - ints[stringListCopy.indexOf(right)]);
    

    Or better, with Comparator:

        String[] strings = new String[]{"string1", "string2", "string3"};
        final int[] ints = new int[]{40, 32, 34};
    
        final List<String> stringListCopy = Arrays.asList(strings);
        ArrayList<String> sortedList = new ArrayList(stringListCopy);
        Collections.sort(sortedList, Comparator.comparing(s -> ints[stringListCopy.indexOf(s)]));
    
    0 讨论(0)
  • 2020-11-30 12:32
    package com.appkart.array;
    
    import java.util.Comparator;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.TreeMap;
    
    public class SortExample {
    
        Map<String, Integer> map = new HashMap<String, Integer>();
        Map<String, Integer> treemap = new TreeMap<String, Integer>(
                new MyComparator(map));
    
        public void addValueInMapAndSort() {
            map.put("string1", 40);
            map.put("string2", 32);
            map.put("string3", 34);
    
            System.out.println(map);
            treemap.putAll(map);
            System.out.println(treemap);
        }
    
    
        class MyComparator implements Comparator<String> {
    
            Map<String, Integer> map;
    
            public MyComparator(Map<String, Integer> map) {
                this.map = map;
            }
    
            @Override
            public int compare(String o1, String o2) {
                if (map.get(o1) >= map.get(o2)) {
                    return 1;
                } else {
                    return -1;
                }
            }
        }
    
        public static void main(String[] args) {
            SortExample example = new SortExample();
            example.addValueInMapAndSort();
        }
    }
    

    Use Comparator for sorting according to value.

    0 讨论(0)
提交回复
热议问题