简体   繁体   中英

List sorting in groovy

I have a book book list and it contains book id, publisher name, contact number, address, book release date and book status (active, deleted, suspended) . I want to sort a list based on the following criteria:

  1. Sort it by activation date
  2. Sort the publisher name from A to Z
  3. If there are two publisher name in the same date range then it should sort it as per book status and the order should be active > suspended > deleted (This is not alphabet sorting)

For example, the result should be:

Activation Date: 18.10.2014
Test Book, ABC publisher, active
Test Book2, ABC publisher, suspended
Book3, XXYYBB publisher, active 

Activation Date: 19.10.2014
Test Book5, XXYYBB publisher, deleted
Test Book3, ZZZZ publisher, active
Test Book4, ZZZZ publisher, suspended

My sample code:

booklist.sort{ x,y ->
  x.activateDate <=> y.activateDate ?: x.publisherName <=> y.publisherName
}

how to do the third manual check for the book status?

Solution 1: enum

If the status is indeed limited to the three exact values given, you should probably already be using something like this anyway:

enum BookStatus { active, suspended, deleted }

Then in the Book class:

class Book {
    ...
    BookStatus status
}

Since Enum classes already have a natural sort order (order of declaration) you are all set, just add another elvis ( ?: ) clause to your comparator closure:

booklist.sort { x, y ->
    x.activateDate <=> y.activateDate ?:
        x.publisherName <=> y.publisherName ?:
        x.status <=> y.status
}

Solution 2: Status-ordering List

See @cfrick 's solution

Solution 3: Status-ordering Map

There are only a couple of minor advantages of this solution over the List-based solution:

  • Average key search through a LinkedHashMap has algorithmic complexity O(1) while average element search through an ArrayList has O(n) .
  • statusOrder[x.status] <=> statusOrder[y.status] is a marginally simpler expression than statusList.indexOf(x.status) <=> statusList.indexOf(y.status)

Here Book.status is assumed to be a String :

final statusOrder = [ active:0, suspended:1, deleted:2 ].asImmutable()
booklist.sort { x, y ->
    x.activateDate <=> y.activateDate ?:
            x.publisherName <=> y.publisherName ?:
            statusOrder[x.status] <=> statusOrder[y.status]
}

If I were for some reason unable to use the Enum solution, I would probably use the List solution unless there were a large (more than 20?) number of status values, in which case I would use the Map solution.

in case these are strings, you can use a list to define the importance and then use the index in this list with the ufo-operator

final order = ['active','suspended','deleted']

def l = [
        [status: 'deleted'],
        [status: 'active'],
        [status: 'suspended'],
        [status: 'active'],
        [status: 'suspended'],
]

println l.sort{ a,b -> order.indexOf(a.status) <=> order.indexOf(b.status) }
// -> [[status:active], [status:active], [status:suspended], [status:suspended], [status:deleted]]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM