groovy-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Paul King <pa...@asert.com.au>
Subject Re: String to Array of Substrings by delimiter
Date Sun, 28 Jun 2015 10:16:17 GMT

Yes, inits/tails has cropped up numerous times in the past, e.g. 2008:
http://hamletdarcy.blogspot.com.au/2008/07/groovy-vs-f-showdown-side-by-side.html

Functional Java also has those methods - though returned in the reverse order.
I prefer Scala's order, i.e. the original then the result of calling init/tail
as many times as elements in the list, i.e. all the way to the empty list.

Cheers, Paul.

On 27/06/2015 9:10 PM, Dinko Srkoč wrote:
> 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.Amerige@sas.com <mailto:Steve.Amerige@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.Amerige@sas.com <mailto:Steve.Amerige@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?
>>
>
>


---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus


Mime
View raw message