1

Hi I have a list of maps in groovy like

def v=[[val1:'FP'],[val1:'LP'],[val1:'MP'],[val1:'MP'],[val1:'LP'],[val1:'FP']]

I wanted to sort based on the following order FP,MP,LP

I tried doing

v.sort{x,y->
  x.val1 <=> y.val1
}

which prints [[val1:FP], [val1:FP], [val1:LP], [val1:LP], [val1:MP], [val1:MP]] which is sorted alphabetically, but I need it to be sorted in the following format FP,MP,LP

dmahapatro
  • 49,365
  • 7
  • 88
  • 117
Siva
  • 289
  • 1
  • 6
  • 16
  • 2
    Create a map associating each string (FP, MP, LP) to an order value (1, 2, 3), and compare the values associated to each string in the comparator. Or use an enum instead of a String. – JB Nizet Nov 20 '16 at 14:34
  • thanks for your reply, Is there any groovier way of doing this? – Siva Nov 20 '16 at 14:42
  • 2
    Not that I know of. But I also don't see what's not groovy about using enums or maps. – JB Nizet Nov 20 '16 at 14:45
  • everything what can't be sorted "alphanumerically" needs to have it's own `comparator`, in this case based on `[ 'b', 'a', 'c' ].indexOf( it )` – injecteer Nov 20 '16 at 15:09

2 Answers2

2

As has been said int the comments, you need to define a preferred order, and then sort based on that... so with your list of maps:

def v=[[val1:'FP'],[val1:'LP'],[val1:'MP'],[val1:'MP'],[val1:'LP'],[val1:'FP']]

And a preferred order of results:

def preferredOrder = ['FP', 'MP', 'LP']

You can then sort based on the values index into this preferred order:

v.sort(false) { preferredOrder.indexOf(it.val1) }

Or, if you want unknown elements (ie: [val1:'ZP']) to go at the end of the sorted list, then you an do:

v.sort(false) { preferredOrder.indexOf(it.val1) + 1 ?: it.val1 }

So if they are not found (index -1) then they are compared on their String name

This question is similar to this one btw, which has more options in the answer

Community
  • 1
  • 1
tim_yates
  • 167,322
  • 27
  • 342
  • 338
2

An alternative: Whenever I am dealing with a fixed, ordered list of strings I immediately think of using enums instead:

enum PValue { FP, MP, LP }

Now we have an ordered set of constants that readily converts to and from string values. So sorting looks as simple as this:

v.sort { x, y -> PValue[x.val1] <=> PValue[y.val1] }

EDIT: Or even simpler:

v.sort { PValue[it.val1] }
BalRog
  • 3,216
  • 23
  • 30