London
London

Reputation: 15274

Sorting java arrayList with predefined order

I have an unsorted list but I want to sort in a custom way i.e.

item_one_primary.pls
item_one_secondary.pls
item_one_last.pls

item_two_last.pls
item_two_primary.pls
item_two_secondary.pls

item_three_secondary.pls
item_three_last.pls
item_three_primary.pls

Here is my predefined order : primary, secondary, last

Above unordered list once the ordering is applied should look like this :

item_one_primary.pls
item_one_secondary.pls
item_one_last.pls

item_two_primary.pls
item_two_secondary.pls
item_two_last.pls

item_three_primary.pls
item_three_secondary.pls
item_three_last.pls

I tried something with comparator but I end up something like this :

item_one_primary.pls
item_two_primary.pls
item_three_primary.pls

...

Does anyone have an idea how to get this sorted?

Here is some code I've used :

List<String> predefinedOrder;

public MyComparator(String[] predefinedOrder) {
        this.predefinedOrder = Arrays.asList(predefinedOrder);
    }

@Override
    public int compare(String item1, String item2) {
        return predefinedOrder.indexOf(item1) - predefinedOrder.indexOf(item2);
    }   

I didn't include the splits(first split by dot(.) second split by underscore(_) to get the item in pre-ordered list).

Upvotes: 5

Views: 3381

Answers (2)

yawn
yawn

Reputation: 8214

A solution using the Google Guava API yields a simple and readable result:

    // some values
    List<String> list = Lists.newArrayList("item_one_primary", "item_one_secondary", "item_one_last");

    // define an explicit ordering that uses the result of a function over the supplied list
    Ordering o = Ordering.explicit("primary", "secondary", "last").onResultOf(new Function<String, String>() {

        // the function splits a values by '_' and uses the last element (primary, secondary etc.)
        public String apply(String input) {
            return Lists.newLinkedList(Splitter.on("_").split(input)).getLast();
        }

    });

    // the ordered result
    System.out.println("o.sortedCopy(list); = " + o.sortedCopy(list));

Upvotes: 2

pconcepcion
pconcepcion

Reputation: 5641

You have to use a Comparator that checks first the item number and only if they are equal, check your predefined order.

Try something like this:

public int compare(Object o1, Object o2) {
        String s1 = (String) o1;
        String s2 = (String) o2;

        String[] a1 = s1.split("_");
        String[] a2 = s2.split("_");

         /* If the primary elements of order are equal the result is 
         the order of the second elements of order */ 
        if (a1[1].compareTo(a2[1]) == 0) { 
            return a1[2].compareTo(a2[2]); 
        /* If they are not equal, we just order by the primary elements */
        } else {
            return a1[1].compareTo(a2[1]);
        }
    }

This is just a basic example, some extra error checking would be nice.

Upvotes: 5

Related Questions