3

I have a String array list totalVals. Each entry in totalVals is a string name and a double loc which is joined into a single string before it was inserted into the array list like:

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

This is how I am given the data. I have separated the values into a string and double array as follows:

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]);
}

Now however, I want to sort the data and put it back into the array list before returning. I want the locs data to be in descending order, which I can do by using Arrays.sort(locs, Collections.reverseOrder());. But I don't know how to sort names so that the names are still associated with the same locations that they were originally.

Example of totalVals: {"Bahamas,32.2233","Zimbabwe,82.2443","India,56.2355","Australia,24.4363"}

Would be split into:

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

Which would then be sorted to:

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

So how would I then sort the two arrays such that the associations at index i in both arrays remain the same?

tushariyer
  • 906
  • 1
  • 10
  • 20
  • 1
    Wrong strategy. Instead of splitting into two arrays, Use a single array of objects, where each object has a name and a loc. Then sort that array. That's what you should be receiving in the first place, instead of strings that you need to parse, if the design was better. – JB Nizet Nov 22 '18 at 16:56

4 Answers4

3

Instead of turning your array into two arrays, turn it into an ArrayList<Pair>

The Pair class is the following :

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
}

And sort your arrays like this :

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

And then split your array into the two arrays.

TheWildHealer
  • 1,546
  • 1
  • 15
  • 26
2

Instead of breaking the arraylist into two different arrays and sorting them separately, sort the ArrayList based on double value in descending order and then break arraylist into two arrays

 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]

Breaking list into double[] array and String[] array

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]

Before java 8 versions

By using `Collections.sort() with custom comparator, and then split the list into two different arrays

 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]
Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98
2

TheWildHealer's solution is short and elegant. Here is below a similar solution for older java platforms, plus a main() method for testing:

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());
        }
    }
}

Result:

Bahamas - 82.2443
Zimbabwe - 56.2355
India - 32.2233
Australia - 24.4363
Amessihel
  • 5,891
  • 3
  • 16
  • 40
2

The method TheWildHealer provided is definitely cleaner than this, but here is a solution which does not require a custom class. Stream the array and map it into arrays/pairs of [String, Integer]. Sort based on second value/Integer and then reconstruct into a string.

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);
flakes
  • 21,558
  • 8
  • 41
  • 88
  • How would I do it without the lambda expressions? I'm using an older version of Java – tushariyer Nov 22 '18 at 17:38
  • @tushariyer This will not work at all with an older version of java (JDK < 8). Streams were introduced at the same time as lambdas. – flakes Nov 22 '18 at 17:39
  • 1
    @tushariyer You'll definitely need to create some classes in this case. Follow the same style as @TheWildHealer, but you'll need to make a new `Comparator` class, seeing as method references were also introduced in JDK 8. eg `Pair::getLoc` and `String[]::new` – flakes Nov 22 '18 at 17:43
  • @tushariyer If possible you should try and get your team to upgrade to the newest JDK 11, or at least up to 8. It has a lot of cool benefits and JDK 11 is guaranteed for long term support from the JDK developers. – flakes Nov 22 '18 at 17:46