54

How to truncate string in groovy?

I used:

def c = truncate("abscd adfa dasfds ghisgirs fsdfgf", 10)

but getting error.

Jay Prall
  • 5,295
  • 5
  • 49
  • 79
Srinath
  • 1,293
  • 3
  • 16
  • 25

5 Answers5

110

The Groovy community has added a take() method which can be used for easy and safe string truncation.

Examples:

"abscd adfa dasfds ghisgirs fsdfgf".take(10)  //"abscd adfa"
"It's groovy, man".take(4)      //"It's"
"It's groovy, man".take(10000)  //"It's groovy, man" (no exception thrown)

There's also a corresponding drop() method:

"It's groovy, man".drop(15)         //"n"
"It's groovy, man".drop(5).take(6)  //"groovy"

Both take() and drop() are relative to the start of the string, as in "take from the front" and "drop from the front".

Online Groovy console to run the examples:
https://ideone.com/zQD9Om(note: the UI is really bad)

For additional information, see "Add a take method to Collections, Iterators, Arrays":
https://issues.apache.org/jira/browse/GROOVY-4865

Dem Pilafian
  • 5,625
  • 6
  • 39
  • 67
11

In Groovy, strings can be considered as ranges of characters. As a consequence, you can simply use range indexing features of Groovy and do myString[startIndex..endIndex].

As an example,

"012345678901234567890123456789"[0..10]

outputs

"0123456789"
Dónal
  • 185,044
  • 174
  • 569
  • 824
Riduidel
  • 22,052
  • 14
  • 85
  • 185
  • 2
    In addition ranges can also be negative with `-1` that means the last character of the string. So whenever you will need to truncate to the last part of a string you can easily do `string[-11..-1]` – Jack Jul 12 '10 at 10:59
  • 1
    this is not working when given "012345"[0..20]. I get the results in loop and some will have more and some dont have more characters. It should apply for the string which exceeds 20 chars. thanks – Srinath Jul 12 '10 at 13:43
  • 3
    In your loop you would need to ensure you only substring if the string is greater than 10, for example, def s = it.size() > 10 ? it[0..10] : it – John Wagenleitner Jul 12 '10 at 14:38
  • @john, yeah meanwhile i applied the same logic and works. thanks – Srinath Jul 12 '10 at 14:40
  • 1
    Range indexing is nice, but if the string is shorter than 10 characters Groovy will throw StringIndexOutOfBoundsException. – Nik Reiman Nov 24 '21 at 16:44
2

To avoid word break you can make use of the java.text.BreakIterator. This will truncate a string to the closest word boundary after a number of characters.

Example

package com.example

import java.text.BreakIterator

class exampleClass { 

    private truncate( String content, int contentLength ) {     
        def result

        //Is content > than the contentLength?
        if(content.size() > contentLength) {  
           BreakIterator bi = BreakIterator.getWordInstance()
           bi.setText(content);
           def first_after = bi.following(contentLength)

           //Truncate
           result = content.substring(0, first_after) + "..."
        } else {
           result = content
        }

        return result
    }
}
seanf
  • 6,504
  • 3
  • 42
  • 52
Tyler Rafferty
  • 3,391
  • 4
  • 28
  • 37
2

we can simply use range indexing features of Groovy and do someString[startIndex..endIndex].

For example:

def str = "abcdefgh"
def outputTrunc = str[2..5]
print outputTrunc

Console:

"cde"
MByD
  • 135,866
  • 28
  • 264
  • 277
1

Here's my helper functions to to solve this kinda problem. In many cases you'll probably want to truncate by-word rather than by-characters so I pasted the function for that as well.

public static String truncate(String self, int limit) {
    if (limit >= self.length())
        return self;

    return self.substring(0, limit);
}

public static String truncate(String self, int hardLimit, String nonWordPattern) {
    if (hardLimit >= self.length())
        return self;

    int softLimit = 0;
    Matcher matcher = compile(nonWordPattern, CASE_INSENSITIVE | UNICODE_CHARACTER_CLASS).matcher(self);
    while (matcher.find()) {
        if (matcher.start() > hardLimit)
            break;

        softLimit = matcher.start();
    }
    return truncate(self, softLimit);
}
rednoah
  • 1,053
  • 14
  • 41