Olia
Olia

Reputation: 811

List elements order depending on complex condition

Let's say, I have a list:

unordered_list = ['c-1','a-2','a-4','b-2','a-1','b-3','c-3','c-4']

And I've got some conditions:

  1. first elements ending with 3 should be appended (but order from a to c should be kept)
  2. then list should be ordered from a to c
  3. but when ordering from a to c the endings must be ordered from 1 to 3

Result should look like:

ordered_list = ['b-3','c-3','a-1','a-2','a-4','b-2','c-1','c-4']

I've spent much time to find some efficient way to realize it in Groovy, but didn't succeed, since I'm beginner in it. Any tips will be much appreciated. Thanks in advance!

Upvotes: 0

Views: 434

Answers (3)

Novaterata
Novaterata

Reputation: 4789

No need for all the other lists, you can stream an array directly

    Stream.concat(Stream.of(unordered_list)
                    .filter(s -> s.endsWith("3"))
                    .sorted(),
            Stream.of(unordered_list))
            .filter(s -> !s.endsWith("3"))
            .sorted()
            .collect(toList());

Or for actual List:

    List<String> unorderedList = asList("c-1", "a-2", "a-4", "b-2", "a-1", "b-3", "c-3", "c-4");
    Stream.concat(unorderedList.stream()
                    .filter(s -> s.endsWith("3"))
                    .sorted(),
            unorderedList.stream()
                    .filter(s1 -> !s1.endsWith("3"))
                    .sorted())
            .collect(toList());

And finally, another way using a partition

    Map<Boolean, List<String>> endsWith3Partition = Stream.of(unordered_list)
            .sorted()
            .collect(partitioningBy(s -> s.endsWith("3")));
    List<String> sorted = new ArrayList<>(unordered.length);
    sorted.addAll(endsWith3Partition.get(true));
    sorted.addAll(endsWith3Partition.get(false));

Upvotes: 2

Darshan Mehta
Darshan Mehta

Reputation: 30819

You can do it by using Java 8's stream, e.g.:

List<String> list = Arrays.asList(new String[]{"c-1","a-2","a-4","b-2","a-1","b-3","c-3","c-4"});

TreeMap<Boolean, List<String>> lists = list.stream()
.collect(Collectors.groupingBy(s -> s.toString().endsWith("3"), TreeMap::new, Collectors.toList()));

final List<String> result = new ArrayList<>();

lists.descendingMap().forEach((k, v) -> {
    Collections.sort(v);
    result.addAll(v);
});

System.out.println(result);

Upvotes: 1

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476659

You can write a comparator, like the one below:

Arrays.sort(unordered_list, new Comparator<String>() {

    @Override
    public int compare(String o1, String o2) {
       String[] o1s = o1.split('-');
       String[] o2s = o2.split('-');
       boolean end1_3 = o1s[1].equals("3");
       boolean end2_3 = o2s[1].equals("3");
       if(end1_3 && end2_3) {
           return 0; //both end with 3
       } else if(end1_3) {
           return -1; //only the first ends with 3, so less than
       } else if(end2_3) {
           return 1; //only the second ends with 3, so greater than
       }
       if(!o1s[0].equals(o2s[0])) { // first group not same
           return o1s[0].compareTo(o2s[0]); // compare first groups
       }
       return o1s[1].compareTo(o2s[1]); // assume equal
    }
});

Upvotes: 2

Related Questions