ruby oneliner vs groovy
-
21-09-2019 - |
Question
i was going through railstutorial and saw the following one liner
('a'..'z').to_a.shuffle[0..7].join
it creates random 7 character domain name like following:
hwpcbmze.heroku.com
seyjhflo.heroku.com
jhyicevg.heroku.com
I tried converting the one liner to groovy but i could only come up with:
def range = ('a'..'z')
def tempList = new ArrayList (range)
Collections.shuffle(tempList)
println tempList[0..7].join()+".heroku.com"
Can the above be improved and made to a one liner? I tried to make the above code shorter by
println Collections.shuffle(new ArrayList ( ('a'..'z') ))[0..7].join()+".heroku.com"
However, apparently Collections.shuffle(new ArrayList ( ('a'..'z') ))
is a null
Solution
Not having shuffle built-in adds the most to the length, but here's a one liner that'll do it:
('a'..'z').toList().sort{new Random().nextInt()}[1..7].join()+".heroku.com"
Yours doesn't work because Collections.shuffle does an inplace shuffle but doesn't return anything. To use that as a one liner, you'd need to do this:
('a'..'z').toList().with{Collections.shuffle(it); it[1..7].join()+".heroku.com"}
OTHER TIPS
It isn't a one-liner, but another Groovy way to do this is to add a shuffle method to String...
String.metaClass.shuffle = { range ->
def r = new Random()
delegate.toList().sort { r.nextInt() }.join()[range]}
And then you have something very Ruby-like...
('a'..'z').join().shuffle(0..7)+'.heroku.com'
This is my attempt. It is a one-liner but allows repetition of characters. It does not perform a shuffle, though it generates suitable output for a random domain name.
I'm posting it as an example of a recursive anonymous closure:
{ i -> i > 0 ? "${(97 + new Random().nextInt(26) as char)}" + call(i-1) : "" }.call(7) + ".heroku.com"
This is definitely not as pretty as the Ruby counterpart but, as Ted mentioned, it's mostly because of the fact that shuffle
method is a static method in Collections
.
[*'a'..'z'].with{ Collections.shuffle it; it }.take(7).join() + '.heroku.com'
I am using the spread operator trick to convert the range into a list :)