Question

I am trying to sort this logically Suppose I have a list of strings that have the follow elements

String[] myList = {"Spring 2013", "Fall 2009", "Fall 2010", "Spring 2012"};

I want to know how I can sort this where the result set would be Fall 2009, Fall 2010, Spring 2012, Spring 2013

I appreciate your help, thanks!

Was it helpful?

Solution 3

In this case, the desired order is the natural (alphabetical) order, so you can use the Arrays.sort(Object\[\]) method. If the desired order does not match the natural order, you can implement a Comparator and use the Arrays.sort(String\[\], Comparator<String>) method.

An example for the Comparator implementation (just to show how it could work):

public class SemesterComparator implements Comparator<String> {

    private static final List<String> SEASONS = Arrays.asList("Spring", "Summer", "Fall", "Winter");

    @Override
    public int compare(String one, String two) {
        String[] partsOne = one.split(" ");
        String[] partsTwo = two.split(" ");
        if (partsOne.length != 2 || partsTwo.length != 2) {
            throw new IllegalArgumentException();
        }
        if (!SEASONS.contains(partsOne[0]) || !SEASONS.contains(partsTwo[0])) {
            throw new IllegalArgumentException();
        }

        // compare years
        int comparison = partsOne[1].compareTo(partsTwo[1]);
        if (comparison == 0) {
            // if years are equal: compare season
            comparison = SEASONS.indexOf(partsOne[0]).compareTo(SEASONS.indexOf(partsTwo[0]));
        }
        return comparison;
    }
}

But as already mentioned in the comments, it would be better to store the values in a format or class that is better sortable.

OTHER TIPS

Presuming you can't reformat the string, you can write a custom comparator that implements that logic. Your Comparator would call split to separate the semester and year. Then it can compare the year first followed by the custom month/semester logic.

You can call Collections.sort or Arrays.sort with a list and your custom comparator.

Note that the the season name such as "Spring" and "Fall" are "less significant" than the year,

Also that the seasons are not to be sorted alphabetically, but as winter, spring, summer, fall (I assume?).

So if you convert "Fall 2010" to "20104" and "Spring 2013" to "20132" then you can sort them as numbers.

Here is how a Comparator#compare function might look like:

int compare(String o1, String o2) {
   // null values always prioritized
   if (o1 == o2) return 0;
   if (o1 == null) return -1;
   if (o2 == null) return 1;

   String[] parts1 = o1.split(' '); // e.g. ["Fall", "2012"]
   String[] parts2 = o2.split(' ');

   // invalid data, just throw some nonsense ordering out
   if (parts1.length != 2 || parts2.length != 2) {
     return parts2.length - parts1.length;
   }

   // have winner, 4 digit years can be compared lexicographical
   var yearCompare = parts[1].compareTo(parts[2]);
   if (yearCompare != 0) {
     return yearCompare;
   }

   // map term names to orderable values
   String[] termWeights = { "Spring", "Summer", "Fall", "Winter" };
   var term1 = termWeights.indexOf(parts1[0]);
   var term2 = termWeights.indexOf(parts2[0]);

   // invalid terms prioritized
   if (term1 == term2) return 0;
   if (term1 == -1) return -1;
   if (term2 == -1) return 1;

   return term2 - term1;
}

Of course, I've not tested this at all. YMMV :)

Here is another alternative approach (based on a comment):

// swap "TermName Year" to "Year TermName"
String prioritizeYear (String i) {
   return i.replaceFirst("^(\\w+)\\s+(\\d+)", "$2_$1");
}

// convert "TermName" to "TermValue"
String weightTerm (String i) {
   return i.replace("Spring", "1")
           .replace("Summer", "2")
           .replace("Fall", "3")
           .replace("Winter", "4");
}

int compare(String o1, String o2) {
   // null values always prioritized
   if (o1 == o2) return 0;
   if (o1 == null) return -1;
   if (o2 == null) return 1;

   String n1 = weightTerm(prioritizeYear(o1));
   String n2 = weightTerm(prioritizeYear(o2));

   return n1.compareTo(n2);
}

Again, YMMV.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top