Schneiden Sie eine Zeichenfolge basierend auf der Zeichenfolgenlänge

136

Ich möchte eine Zeichenfolge kürzen, wenn die Länge 10 Zeichen überschreitet.

Angenommen, die Zeichenfolgenlänge beträgt 12 ( String s="abcdafghijkl"), dann enthält die neue zugeschnittene Zeichenfolge "abcdefgh..".

Wie kann ich das erreichen?

yshak
quelle
6
mögliches Duplikat von bis zu ersten N Zeichen
Stephen C
Zu Ihrer Information , eine HORIZONTALE ELLIPSIS ist ein einzelnes Zeichen, nicht zwei oder drei FULL STOP- Zeichen:…
Basil Bourque

Antworten:

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

Durch die Verwendung Math.mindieser Option wird eine Ausnahme vermieden, wenn die Zeichenfolge bereits kürzer als ist 10.


Anmerkungen:

  1. Das obige macht echtes Trimmen. Wenn Sie die letzten drei (!) Zeichen tatsächlich durch Punkte ersetzen möchten, wenn sie abgeschnitten werden, verwenden Sie Apache Commons StringUtils.abbreviate.

  2. Dies kann sich falsch verhalten 1, wenn Ihre Zeichenfolge Unicode-Codepunkte außerhalb des BMP enthält. zB Emojis. Eine (kompliziertere) Lösung, die für alle Unicode-Codepunkte ordnungsgemäß funktioniert, finden Sie unter @ sibnicks Lösung .


1 - Ein Unicode-Codepunkt, der sich nicht auf Ebene 0 befindet (BMP), wird in der als "Ersatzpaar" (dh zwei charWerte) dargestellt String. Wenn wir dies ignorieren, können wir auf weniger als 10 Codepunkte zuschneiden oder (schlimmer) mitten in einem Ersatzpaar abschneiden. Auf der anderen Seite String.length()ist dies kein ideales Maß für die Unicode-Textlänge mehr. Daher kann das Zuschneiden basierend darauf die falsche Vorgehensweise sein.

Stephen C.
quelle
Können wir anstelle von Math.min keine bedingte Prüfung durchführen und nur dann Teilzeichenfolgen ausführen, wenn die maximale Zeichenfolge dann erforderlich ist? zB:s = (s.length() > 10) ? s.substring(0,10) : s ;
rram
1
Natürlich kannst du. Lesen Sie die anderen Antworten, um das Problem auf andere Weise zu lösen!
Stephen C
132

StringUtils.abbreviateaus der Apache Commons Lang Bibliothek könnte dein Freund sein:

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

Mit Commons Lang3 können Sie sogar einen benutzerdefinierten String als Ersatzmarker festlegen. Hiermit können Sie beispielsweise eine einzelne Auslassungsstelle festlegen.

StringUtils.abbreviate("abcdefg", "\u2026", 6) = "abcde…"
H6.
quelle
5
Es könnte sein, aber die Frage des OP fragt nicht nach "Auslassungspunkten".
Stephen C
9
@StephenC - Die Frage zeigt 8 Zeichen, gefolgt von 2 Punkten bei einer Längenbeschränkung von 10, was einer Ellipse sehr ähnlich ist (nur 2 Punkte statt 3). Es ist auch wahrscheinlich, dass viele der Leute, die diese Frage finden, eine Ellipse als nützlich erachten.
ToolmakerSteve
12
... und wenn Sie die Auslassungspunkte nicht möchten, kann Ihnen StringUtils.left () helfen.
Superole
1
Zu Ihrer Information , eine HORIZONTALE ELLIPSIS ist ein einzelnes Zeichen, nicht drei FULL STOP- Zeichen:…
Basil Bourque
53

Es gibt eine StringUtilsFunktion, die dies tut.

s = StringUtils.left(s, 10)

Wenn len Zeichen nicht verfügbar sind oder der String null ist, wird der String ausnahmslos zurückgegeben. Ein leerer String wird zurückgegeben, wenn len negativ ist.

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

Mit freundlicher Genehmigung von Steeve McCauley

Mulki
quelle
22

Wie üblich kümmert sich niemand um UTF-16-Ersatzpaare. Siehe dazu: Was sind die am häufigsten verwendeten Nicht-BMP-Unicode-Zeichen? Sogar Autoren von org.apache.commons / commons-lang3

In diesem Beispiel sehen Sie den Unterschied zwischen korrektem und normalem Code:

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)));
    }
}
Geschwister
quelle
1
Fand den Fehler in Apache Commons 'Jira: Issues.apache.org/jira/browse/LANG-1343
Ryan Quinn
10

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

shift66
quelle
16
Der zweite Parameter der Teilzeichenfolge ist exklusiv, daher wird bei dieser Antwort der String auf 9 Zeichen gekürzt.
Emulcahy
8

Oder Sie können diese Methode einfach verwenden, wenn Sie StringUtils nicht zur Hand haben:

public static String abbreviateString(String input, int maxLength) {
    if (input.length() <= maxLength) 
        return input;
    else 
        return input.substring(0, maxLength-2) + "..";
}
MVojtkovszky
quelle
4

Nur für den Fall, dass Sie nach einer Möglichkeit suchen, die LETZTEN 10 Zeichen einer Zeichenfolge zu kürzen und beizubehalten.

s = s.substring(Math.max(s.length(),10) - 10);
rekotc
quelle
2

Mit Kotlin ist es so einfach wie:

yourString.take(10)

Gibt eine Zeichenfolge zurück, die die ersten n Zeichen dieser Zeichenfolge enthält, oder die gesamte Zeichenfolge, wenn diese Zeichenfolge kürzer ist.

Dokumentation

Leo Droidcoder
quelle
1

tl; dr

Sie scheinen beim Abschneiden an letzter Stelle nach einem Auslassungszeichen ( ) zu fragen . Hier ist ein Einzeiler zum Bearbeiten Ihrer Eingabezeichenfolge.

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

Sehen Sie diesen Code live auf IdeOne.com.

abcdefghi…

Ternärer Operator

Mit dem ternären Operator können wir einen Einzeiler erstellen .

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.
;

Sehen Sie diesen Code live auf IdeOne.com.

abcdefghi…

Java-Streams

Die Java Streams-Funktion macht dies ab Java 9 und höher interessant. Interessant, aber vielleicht nicht der beste Ansatz.

Wir verwenden Codepunkte anstelle von charWerten. Der charTyp ist Legacy und beschränkt sich auf eine Teilmenge aller möglichen Unicode- Zeichen.

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()
        ;

Wenn überschüssige Zeichen abgeschnitten wurden, ersetzen Sie das letzte Zeichen durch ein Auslassungszeichen .

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

Wenn ich mir nur eine Möglichkeit vorstellen könnte, die Stream-Linie mit dem Teil "Wenn das Limit überschritten wird, mache Auslassungspunkte" zusammenzusetzen.

Basil Bourque
quelle
Nein. Natürlich möchte er die Länge der Saite kürzen, wenn sie eine Länge von 11 oder mehr erreicht. Sie müssen an einem neuen KI-System arbeiten oO
JD333
1
@ JD333 Dein Kommentar entgeht mir. Das Abschneiden auf eine Länge von 10 einschließlich der Auslassungspunkte ist genau das, was ich hier zeige.
Basil Bourque
0
str==null ? str : str.substring(0, Math.min(str.length(), 10))

oder,

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

Funktioniert mit null.

aceminds
quelle