Sort the list in groovy in an unusual way

I have a list, say [Cat, Dog, Cow, Horse], which I want to sort as follows

  • If Cat is listed, it should appear first.
  • If the cow is on the list, it must be second
  • The remaining elements should appear in alphabetical order.

Any suggestions on how this can be done in groovy?

+6
source share
6 answers

Tim's answer is pretty smart. I'm personally more of a fan of just using list operations, as the code they create is a little easier to read.

def highPriority = [ 'Cat', 'Cow' ] def list = [ 'Armadillo', 'Dog', 'Cow', 'Zebra', 'Horse', 'Cow', 'Cat' ] def remainder = ( list - highPriority ).sort() list.retainAll( highPriority ) list.sort{ highPriority.indexOf( it ) } + remainder 

This will give you a cow twice. If you don't want duplicates, using intersection is pretty simple.

 def highPriority = [ 'Cat', 'Cow' ] def list = [ 'Armadillo', 'Dog', 'Cow', 'Zebra', 'Horse', 'Cow', 'Cat' ] list.intersect( highPriority ).sort{ highPriority.indexOf( it ) } + ( list - highPriority ).sort() 
+7
source

This should do it:

 // Define our input list def list = [ 'Armadillo', 'Cat', 'Dog', 'Cow', 'Zebra', 'Horse', 'Cow' ] // Define a closure that will do the sorting def sorter = { String a, String b, List prefixes=[ 'Cat', 'Cow' ] -> // Get the index into order for a and b // if not found, set to being Integer.MAX_VALUE def (aidx,bidx) = [a,b].collect { prefixes.indexOf it }.collect { it == -1 ? Integer.MAX_VALUE : it } // Compare the two indexes. // If they are the same, compare alphabetically aidx <=> bidx ?: a <=> b } // Create a new list by sorting using our closure def sorted = list.sort false, sorter // Print it out println sorted 

What prints:

 [Cat, Cow, Cow, Armadillo, Dog, Horse, Zebra] 

I commented on this to try to explain every step that is required. Adding default prefix elements as an optional parameter in sorter closure means that we can do things like this to change the default value:

 // Use Dog, Zebra, Cow as our prefix items def dzc = list.sort false, sorter.rcurry( [ 'Dog', 'Zebra', 'Cow' ] ) println dzc 

Which then prints a list sorted as:

 [Dog, Zebra, Cow, Cow, Armadillo, Cat, Horse] 
+6
source

Here's another alternative that seems easier to me:

 // smaller values get sorted first def priority(animal) { animal in ['Cat', 'Cow'] ? 0 : 1 } def list = [ 'Armadillo', 'Cat', 'Dog', 'Cow', 'Zebra', 'Horse', 'Cow' ] def sorted = list.sort{ a, b -> priority(a) <=> priority(b) ?: a <=> b } assert sorted == ['Cat', 'Cow', 'Cow', 'Armadillo', 'Dog', 'Horse', 'Zebra'] 
+1
source

If you don't have duplicate elements, you can try the following:

 def highPriority = [ 'Cat', 'Cow' ] def list = [ 'Armadillo', 'Dog', 'Cow', 'Zebra', 'Horse', 'Cat' ] highPriority + list.minus(highPriority).sort() 
0
source

Inspired by tomas' :

 def highPriority = [ 'Cat', 'Cow' ] def list = [ 'Armadillo', 'Cat', 'Dog', 'Cow', 'Zebra', 'Horse', 'Cow' ] // Group animals by priority. def groups = list.groupBy { it in highPriority ? it : 'rest' } // High priority animals are sorted by priority and the rest alphabetically. def sorted = highPriority.collectMany { groups[it] } + groups['rest'].sort() assert sorted == ['Cat', 'Cow', 'Cow', 'Armadillo', 'Dog', 'Horse', 'Zebra'] 

The groups variable is similar to [rest:[Armadillo, Dog, Zebra, Horse], Cat:[Cat], Cow:[Cow, Cow]] .

Another, possibly less reliable solution might be:

 def sorted = list.sort(false) { def priority = highPriority.indexOf(it) if (priority == -1) priority = highPriority.size() // Sort first by priority and then by the value itself "$priority$it" } 

It is less reliable in the sense that it sorts strings like "2Armadillo" , "0Cat" , etc., and will not work if you have 9 or more high-priority animals (because "10Alpaca" < "9Eel" if Groovy provided some comparable type of tuple, for example Python tuples , so instead of returning "$priority$it" as a comparable key, you can return the tuple (priority, it) .

0
source

This question is quite old, but today I found that Groovy has a rather undocumented OrderBy comparator that can be used in this case:

 def highPriority = ['Cow', 'Cat'] def list = ['Armadillo', 'Cat', 'Dog', 'Cow', 'Zebra', 'Horse', 'Cow'] def sorted = list.sort new OrderBy([{ -highPriority.indexOf(it) }, { it }]) assert sorted == ['Cat', 'Cow', 'Cow', 'Armadillo', 'Dog', 'Horse', 'Zebra'] 

The OrderBy comparator first compares the animals using their index in the highPriority list, which is canceled (so animals that do not have high priority (i.e., index -1) move to the end of the list), and if the indices are equal, they compare them using the function identities {it} , which, since animals are strings, sorts them alphabetically.

0
source

Source: https://habr.com/ru/post/910792/


All Articles