I know the solution has been found, but it’s a nice problem. Here’s my contribution, however inapplicable…
This is the second time 1 <http://groovy.329449.n5.nabble.com/Find-sublists-adhering-to-some-rules-tp5720013p5720087.html>*, I believe, that the method inits from the Scala collection API 2 <http://scala-lang.org/api/current/index.html#scala.collection.TraversableLike@inits:Iterator[Repr]> seems usable. (is this enough to add it to groovy-jdk?) inits returns successive application of init() on a collection: [1, 2, 3].inits() would return [[1, 2, 3], [1, 2], [1], []] The naive implementation of inits might look like this: class Inits { static List<List> inits(List self) { (1..self.size()).inject([self]) { acc, _ -> acc << acc.last().init() } } } Finally, the solution: String s = '/a/b/c/d'def expected = ['/a', '/a/b', '/a/b/c', '/a/b/c/d'] use (Inits) { def res = s.tokenize('/').inits().reverse().tail().collect { '/' + it.join('/') } assert res == expected } Cheers, Dinko (*) unlike before, unfortunately, this permalink won’t lead directly to my post, one has to scroll to the bottom of the page to find it On 26 June 2015 at 20:59, Steve Amerige <steve.amer...@sas.com> wrote: > Hi Shil, > > I like this... thanks! I've made the following first improvements by > using *tokenize *instead of *split *and using a single Groovy string to > clean up the syntax a bit: > > String s = '/a/b/c/d' > s.tokenize('/').inject([]) { acc, val -> acc + "${acc ? acc.last() : > ''}/$val" } > > * Result: [/a, /a/b, /a/b/c, /a/b/c/d]* > > > Then, to get rid of the ternary logic, I thought about adding a *withDefault > *expression so that I could safely use last(): > > String s = '/a/b/c/d' > s.tokenize('/').inject([]*.withDefault {''}*) { acc, val -> acc + "${ > *acc.last()*}/$val" } > > But the above throws *NoSuchElementException *when trying to reference > *acc.last()*. It does make sense: getting a default implies that an > entry in the list gets created, but we don't want to create an object into > the list. So, one could add a delegate to solve this without dirtying the > semantics of *last*: > > String s = '/a/b/c/d' > List.metaClass.safelast = { delegate?.empty ? '' : delegate.last() } > s.tokenize('/').inject([]) { acc, val -> acc + > "${acc.safelast()}/$val" } > > Thanks again Shil and Bahman for your ideas! > > Enjoy, > Steve Amerige > Principal Software Developer, Fraud and Compliance Solutions Development > SAS Institute, 100 SAS Campus Dr, Room U3050, Cary, NC 27513-8617 > > > > On 6/26/2015 12:09 PM, Shil Sinha wrote: > > Not the best looking, but it's a one liner that works: > > s.split('/').tail().inject([]) { acc, val -> acc + ((!acc.isEmpty() ? > acc.last() : '') + "/$val") } > > > On Fri, Jun 26, 2015 at 11:34 AM, Steve Amerige <steve.amer...@sas.com> > wrote: > >> Hi all, >> >> Suppose you have: >> >> String s = '/a/b/c/d' // guaranteed to begin with a / and have at >> least one substring sequence after the /; can have more than 4 as shown in >> this example >> >> and I want the result: >> >> [ '/a', '/a/b', '/a/b/c', '/a/b/c/d' ] >> >> where '/' can be any single character delimiter. What would be the >> easiest, grooviest way to get that result? >> > >