Couper une chaîne en fonction de la longueur de la chaîne

136

Je veux couper une chaîne si la longueur dépasse 10 caractères.

Supposons que si la longueur de la chaîne est 12 ( String s="abcdafghijkl"), la nouvelle chaîne tronquée contiendra "abcdefgh..".

Comment puis-je atteindre cet objectif?

yshak
la source
6
duplication possible jusqu'à N premiers caractères
Stephen C
Pour info, une ELLIPSIE HORIZONTALE est un seul caractère, pas deux ou trois caractères FULL STOP :…
Basil Bourque

Réponses:

262
s = s.substring(0, Math.min(s.length(), 10));

Utiliser Math.mincomme ceci évite une exception dans le cas où la chaîne est déjà plus courte que 10.


Remarques:

  1. Ce qui précède fait une vraie coupe. Si vous souhaitez réellement remplacer les trois derniers caractères (!) Par des points si cela tronque, utilisez Apache Commons StringUtils.abbreviate.

  2. Cela peut se comporter de manière incorrecte 1 si votre chaîne contient des points de code Unicode en dehors du BMP; par exemple Emojis. Pour une solution (plus compliquée) qui fonctionne correctement pour tous les points de code Unicode, voir la solution de @ sibnick .


1 - Un point de code Unicode qui n'est pas sur le plan 0 (le BMP) est représenté comme une "paire de substitution" (c'est-à-dire deux charvaleurs) dans le String. En ignorant cela, nous pourrions réduire à moins de 10 points de code, ou (pire) tronquer au milieu d'une paire de substitution. D'autre part, ce String.length()n'est plus une mesure idéale de la longueur du texte Unicode, donc le rognage en fonction de cela peut être la mauvaise chose à faire.

Stephen C
la source
Au lieu de Math.min, ne pouvons-nous pas faire une vérification conditionnelle et faire une sous-chaîne uniquement si la chaîne est max alors requise? par exemple:s = (s.length() > 10) ? s.substring(0,10) : s ;
rram
1
Oui bien sûr, vous pouvez. Lisez les autres réponses pour découvrir d'autres moyens de résoudre le problème!
Stephen C
132

StringUtils.abbreviatede la bibliothèque Apache Commons Lang pourrait être votre ami:

StringUtils.abbreviate("abcdefg", 6) = "abc..."
StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
StringUtils.abbreviate("abcdefg", 4) = "a..."

Commons Lang3 permet même de définir une chaîne personnalisée comme marqueur de remplacement. Avec cela, vous pouvez par exemple définir une seule ellipse de caractère.

StringUtils.abbreviate("abcdefg", "\u2026", 6) = "abcde…"
H6.
la source
5
C'est possible, mais la question du PO ne demande pas de "points de suspension".
Stephen C
9
@StephenC - La question montre 8 caractères suivis de 2 points, étant donné une longueur limite de 10, ce qui ressemble beaucoup à une ellipse (juste 2 points au lieu de 3). Il est également probable que de nombreuses personnes qui trouvent cette question considèrent qu'une ellipse est utile.
ToolmakerSteve
12
... et si vous ne voulez pas les points de suspension, alors StringUtils.left () peut vous aider.
Superole
1
Pour info, une ELLIPSIE HORIZONTALE est un seul caractère, pas trois caractères FULL STOP :…
Basil Bourque
53

Il existe une StringUtilsfonction Apache Commons qui fait cela.

s = StringUtils.left(s, 10)

Si les caractères len ne sont pas disponibles ou si la chaîne est nulle, la chaîne sera renvoyée sans exception. Une chaîne vide est renvoyée si len est négatif.

StringUtils.left (null, ) = null
StringUtils.left (
, -ve) = ""
StringUtils.left ("", *) = ""
StringUtils.left ("abc", 0) = ""
StringUtils.left (" abc ", 2) =" ab "
StringUtils.left (" abc ", 4) =" abc "

StringUtils.Left JavaDocs

Gracieuseté: Steeve McCauley

Mulki
la source
22

Comme d'habitude, personne ne se soucie des paires de substituts UTF-16. Voir à leur sujet: Quels sont les caractères Unicode non BMP les plus couramment utilisés? Même les auteurs de org.apache.commons / commons-lang3

Vous pouvez voir la différence entre le code correct et le code habituel dans cet exemple:

public static void main(String[] args) {
    //string with FACE WITH TEARS OF JOY symbol
    String s = "abcdafghi\uD83D\uDE02cdefg";
    int maxWidth = 10;
    System.out.println(s);
    //do not care about UTF-16 surrogate pairs
    System.out.println(s.substring(0, Math.min(s.length(), maxWidth)));
    //correctly process UTF-16 surrogate pairs
    if(s.length()>maxWidth){
        int correctedMaxWidth = (Character.isLowSurrogate(s.charAt(maxWidth)))&&maxWidth>0 ? maxWidth-1 : maxWidth;
        System.out.println(s.substring(0, Math.min(s.length(), correctedMaxWidth)));
    }
}
sibnick
la source
1
Trouvé le bogue dans la jira d'Apache commons: issues.apache.org/jira/browse/LANG-1343
Ryan Quinn
10

s = s.length() > 10 ? s.substring(0, 9) : s;

shift66
la source
16
Le deuxième paramètre de sous-chaîne est exclusif, donc cette réponse réduit la chaîne à 9 caractères.
emulcahy
8

Ou vous pouvez simplement utiliser cette méthode au cas où vous n'avez pas StringUtils sous la main:

public static String abbreviateString(String input, int maxLength) {
    if (input.length() <= maxLength) 
        return input;
    else 
        return input.substring(0, maxLength-2) + "..";
}
MVojtkovszky
la source
Votre code n'a pas fonctionné pour moi. Essayez ceciSystem.out.println(abbreviateString("ABC\ud83d\udc3bDEF", 6));
T3rm1
4

Juste au cas où vous cherchez un moyen de couper et de conserver les 10 DERNIERS caractères d'une chaîne.

s = s.substring(Math.max(s.length(),10) - 10);
rekotc
la source
3

Avec Kotlin, c'est aussi simple que:

yourString.take(10)

Renvoie une chaîne contenant les n premiers caractères de cette chaîne, ou la chaîne entière si cette chaîne est plus courte.

Documentation

Leo Droidcoder
la source
1

tl; dr

Vous semblez demander un caractère points de suspension ( ) à la dernière place, lors de la troncature. Voici une ligne unique pour manipuler votre chaîne d'entrée.

String input = "abcdefghijkl";
String output = ( input.length () > 10 ) ? input.substring ( 0 , 10 - 1 ).concat ( "…" ) : input;

Voir ce code exécuté en direct sur IdeOne.com.

abcdefghi…

Opérateur ternaire

Nous pouvons faire un one-liner en utilisant l' opérateur ternaire .

String input = "abcdefghijkl" ;

String output = 
    ( input.length() > 10 )          // If too long…
    ?                                
    input     
    .substring( 0 , 10 - 1 )         // Take just the first part, adjusting by 1 to replace that last character with an ellipsis.
    .concat( "…" )                   // Add the ellipsis character.
    :                                // Or, if not too long…
    input                            // Just return original string.
;

Voir ce code exécuté en direct sur IdeOne.com.

abcdefghi…

Flux Java

La fonction Java Streams rend cela intéressant, à partir de Java 9 et versions ultérieures. Intéressant, mais peut-être pas la meilleure approche.

Nous utilisons des points de code plutôt que des charvaleurs. Le chartype est hérité et est limité au sous-ensemble de tous les caractères Unicode possibles .

String input = "abcdefghijkl" ;
int limit = 10 ;
String output =
        input
                .codePoints()
                .limit( limit )
                .collect(                                    // Collect the results of processing each code point.
                        StringBuilder::new,                  // Supplier<R> supplier
                        StringBuilder::appendCodePoint,      // ObjIntConsumer<R> accumulator
                        StringBuilder::append                // BiConsumer<R,​R> combiner
                )
                .toString()
        ;

Si nous avions des caractères en excès tronqués, remplacez le dernier caractère par des points de suspension .

if ( input.length () > limit )
{
    output = output.substring ( 0 , output.length () - 1 ) + "…";
}

Si seulement je pouvais penser à un moyen de mettre en place la ligne de flux avec la partie "si la limite dépasse, faites des points de suspension".

Basil Bourque
la source
Non. De toute évidence, il veut couper la longueur de la corde si elle atteint une longueur de 11 ou plus. Vous devez travailler sur un nouveau système d'IA oO
JD333
1
@ JD333 Votre commentaire m'échappe. La troncature à une longueur de 10, y compris les points de suspension, est exactement ce que je montre ici.
Basil Bourque
0
str==null ? str : str.substring(0, Math.min(str.length(), 10))

ou,

str==null ? "" : str.substring(0, Math.min(str.length(), 10))

Fonctionne avec null.

aceminds
la source