Обрезать строку в зависимости от длины строки

136

Я хочу обрезать строку, если длина превышает 10 символов.

Предположим, что если длина строки равна 12 ( String s="abcdafghijkl"), тогда новая обрезанная строка будет содержать "abcdefgh..".

Как мне этого добиться?

yshak
источник
6
возможное дублирование до первых N символов
Stephen C
К вашему сведению, ГОРИЗОНТАЛЬНЫЙ ЭЛЛИПСИС - это один символ, а не два или три символа
Бэзил Бурк

Ответы:

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

С помощью Math.min like this позволяет избежать исключения в случае, когда строка уже короче, чем 10.


Ноты:

  1. Вышеупомянутое делает настоящую обрезку. Если вы действительно хотите заменить последние три (!) Символа точками, если он усекается, используйте Apache CommonsStringUtils.abbreviate .

  2. Это может вести себя неправильно 1, если ваша строка содержит кодовые точки Unicode вне BMP; например, Emojis. Для (более сложного) решения , которое работает правильно для всех Unicode кодовых точек, см @ sibnick - й решение .


1 - Кодовая точка Unicode, которая не находится в плоскости 0 (BMP), представлена ​​как «суррогатная пара» (т. Е. Два charзначения) в String. Игнорируя это, мы можем обрезать менее 10 кодовых точек или (что еще хуже) обрезать в середине суррогатной пары. С другой стороны, String.length()это уже не идеальная мера длины текста Unicode, поэтому обрезка на ее основе может быть неправильным решением.

Стивен С
источник
Вместо Math.min не можем ли мы выполнить условную проверку и сделать подстроку только в том случае, если строка является максимальной, а это необходимо? например:s = (s.length() > 10) ? s.substring(0,10) : s ;
rram
1
Да, конечно ты можешь. Прочтите другие ответы, чтобы узнать о других способах решения проблемы!
Stephen C
132

StringUtils.abbreviateиз библиотеки Apache Commons Lang может быть вашим другом:

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

Commons Lang3 даже позволяет установить пользовательскую строку в качестве маркера замены. С его помощью вы можете, например, установить односимвольный многоточие.

StringUtils.abbreviate("abcdefg", "\u2026", 6) = "abcde…"
H6.
источник
5
Может быть, но вопрос ОП не требует "многоточия".
Стивен С.
9
@StephenC - вопрос показывает 8 символов, за которыми следуют 2 точки, с учетом ограничения длины 10, что очень похоже на многоточие (всего 2 точки, а не 3). Также вероятно, что многие люди, задавшие этот вопрос, сочтут многоточие полезным.
ToolmakerSteve
12
... и если вам не нужно многоточие, вам может помочь StringUtils.left ().
Superole
1
К вашему сведению, ГОРИЗОНТАЛЬНЫЙ ЭЛЛИПСИС - это один символ, а не три символа
Бэзил Бурк,
53

Для этого есть StringUtilsфункция Apache Commons .

s = StringUtils.left(s, 10)

Если символы len недоступны или String имеет значение null, String будет возвращен без исключения. Если len отрицательное, возвращается пустая строка.

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

Предоставлено: Стив Макколи.

Мульки
источник
22

Как обычно, никому нет дела до суррогатных пар UTF-16. См. О них: Какие символы Unicode, отличные от BMP, наиболее часто используются на практике? Даже авторы org.apache.commons / commons-lang3

В этом примере вы можете увидеть разницу между правильным кодом и обычным кодом:

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
источник
1
Обнаружил ошибку в jira сообщества Apache: issues.apache.org/jira/browse/LANG-1343
Райан Куинн
10

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

shift66
источник
16
Второй параметр подстроки является эксклюзивным, поэтому этот ответ обрезает строку до 9 символов.
emulcahy 03
8

Или вы можете просто использовать этот метод, если у вас нет StringUtils под рукой:

public static String abbreviateString(String input, int maxLength) {
    if (input.length() <= maxLength) 
        return input;
    else 
        return input.substring(0, maxLength-2) + "..";
}
MVojtkovszky
источник
Ваш код у меня не работал. Попробуйте этоSystem.out.println(abbreviateString("ABC\ud83d\udc3bDEF", 6));
T3rm1
4

На всякий случай вы ищете способ обрезать и сохранить ПОСЛЕДНИЕ 10 символов строки.

s = s.substring(Math.max(s.length(),10) - 10);
rekotc
источник
3

С Kotlin это так же просто, как:

yourString.take(10)

Возвращает строку, содержащую первые n символов этой строки, или всю строку, если эта строка короче.

Документация

Лев Droidcoder
источник
1

ТЛ; др

Кажется, вы запрашиваете символ многоточия ( ) в последнем месте при усечении. Вот однострочник для управления вашей входной строкой.

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

Посмотри это код запускается вживую на IdeOne.com.

ABCDEFGHI ...

Тернарный оператор

Мы можем сделать однострочник, используя тернарный оператор .

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

Посмотрите, как этот код запускается вживую на IdeOne.com.

ABCDEFGHI ...

Потоки Java

Средство Java Streams делает это интересным, начиная с Java 9 и новее. Интересный, но, может быть, не лучший подход.

Мы используем кодовые точки, а не charзначения. charТип наследство, и ограничивается подмножество всех возможных Unicode символов.

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

Если у нас были усечены лишние символы, замените последний символ многоточием .

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

Если бы я только мог придумать способ соединить линию потока с частью «если превышено ограничение, сделай многоточие».

Базилик Бурк
источник
Нет. Ясно, что он хочет сократить длину струны, если она достигает длины 11 или более. Вы, должно быть, работаете над новой системой искусственного интеллекта oO
JD333 02
1
@ JD333 Ваш комментарий ускользнул от меня. Усечение до длины 10, включая многоточие, - это именно то, что я показываю здесь.
Basil
0
str==null ? str : str.substring(0, Math.min(str.length(), 10))

или,

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

Работает с null.

aceminds
источник