Potong tali berdasarkan panjang tali

136

Saya ingin memotong string jika panjangnya melebihi 10 karakter.

Misalkan jika panjang string adalah 12 ( String s="abcdafghijkl"), maka string yang baru dipangkas akan berisi "abcdefgh..".

Bagaimana saya bisa mencapai ini?

yshak
sumber
6
kemungkinan duplikat hingga karakter N pertama
Stephen C
FYI, a HORIZONTAL ELLIPSIS adalah karakter tunggal, bukan dua atau tiga karakter STOP LENGKAP : ...
Basil Bourque

Jawaban:

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

Menggunakan Math.minseperti ini menghindari pengecualian dalam kasus di mana string sudah lebih pendek dari 10.


Catatan:

  1. Di atas tidak pemangkasan nyata. Jika Anda benar-benar ingin mengganti tiga (!) Karakter terakhir dengan titik-titik jika terpotong, maka gunakan Apache Commons StringUtils.abbreviate.

  2. Ini mungkin berperilaku salah 1 jika String Anda berisi titik kode Unicode di luar BMP; mis. Emoji. Untuk solusi (lebih rumit) yang bekerja dengan benar untuk semua titik kode Unicode, lihat solusi @ sibnick .


1 - Suatu titik kode Unicode yang tidak ada pada bidang 0 (BMP) diwakili sebagai "pasangan pengganti" (yaitu dua charnilai) di String. Dengan mengabaikan ini, kita mungkin memotong kurang dari 10 poin kode, atau (lebih buruk) memotong di tengah pasangan pengganti. Di sisi lain, String.length()bukan lagi ukuran ideal panjang teks Unicode, jadi memangkas berdasarkan itu mungkin merupakan hal yang salah untuk dilakukan.

Stephen C
sumber
Alih-alih Math.min tidak bisakah kita melakukan pemeriksaan bersyarat dan melakukan substring hanya jika string maksimum maka diperlukan? mis:s = (s.length() > 10) ? s.substring(0,10) : s ;
rram
1
Ya, tentu saja kamu bisa. Baca jawaban lain untuk cara lain untuk menyelesaikan masalah!
Stephen C
132

StringUtils.abbreviatedari perpustakaan Apache Commons Lang bisa menjadi teman Anda:

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

Commons Lang3 bahkan memungkinkan untuk mengatur String khusus sebagai penanda pengganti. Dengan ini Anda dapat, misalnya, mengatur elipsis karakter tunggal.

StringUtils.abbreviate("abcdefg", "\u2026", 6) = "abcde…"
H6.
sumber
5
Bisa jadi, tetapi pertanyaan OP tidak meminta "elipsis".
Stephen C
9
@StephenC - Pertanyaan menunjukkan 8 karakter diikuti oleh 2 titik, diberi batas panjang 10, yang sangat mirip dengan elipsis (hanya 2 titik daripada 3). Mungkin juga banyak orang yang menemukan pertanyaan ini akan menganggap elips berguna.
ToolmakerSteve
12
... dan jika Anda tidak menginginkan ellipsis, maka StringUtils.left () dapat membantu Anda.
Superole
1
FYI, a HORIZONTAL ELLIPSIS adalah karakter tunggal, bukan tiga karakter FULL STOP : ...
Basil Bourque
53

Ada StringUtilsfungsi Apache Commons yang melakukan ini.

s = StringUtils.left(s, 10)

Jika len karakter tidak tersedia, atau String adalah null, String akan dikembalikan tanpa kecuali. String kosong dikembalikan jika len negatif.

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

Courtesy: Steeve McCauley

Mulki
sumber
22

Seperti biasa tidak ada yang peduli tentang pasangan pengganti UTF-16. Lihat tentang mereka: Apa karakter Unicode non-BMP paling umum dalam penggunaan aktual? Bahkan penulis dari org.apache.commons / commons-lang3

Anda dapat melihat perbedaan antara kode yang benar dan kode biasa dalam sampel ini:

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
sumber
1
Menemukan bug di jira
Ryan Quinn
10

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

shift66
sumber
16
Param substring kedua bersifat eksklusif, jadi jawaban ini memangkas String menjadi 9 karakter.
emulcahy
8

Atau Anda bisa menggunakan metode ini jika Anda tidak memiliki StringUtils di tangan:

public static String abbreviateString(String input, int maxLength) {
    if (input.length() <= maxLength) 
        return input;
    else 
        return input.substring(0, maxLength-2) + "..";
}
MVojtkovszky
sumber
Kode Anda tidak berfungsi untuk saya. Coba iniSystem.out.println(abbreviateString("ABC\ud83d\udc3bDEF", 6));
T3rm1
4

Untuk berjaga-jaga jika Anda mencari cara untuk memotong dan menjaga 10 karakter TERAKHIR string.

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

Dengan Kotlin itu sesederhana:

yourString.take(10)

Mengembalikan string yang berisi n karakter pertama dari string ini, atau seluruh string jika string ini lebih pendek.

Dokumentasi

Leo Droidcoder
sumber
1

tl; dr

Anda tampaknya meminta karakter ellipsis ( ) di tempat terakhir, saat memotong. Berikut ini adalah satu-liner untuk memanipulasi string input Anda.

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

Lihat kode ini berjalan langsung di IdeOne.com.

abcdefghi ...

Operator ternary

Kita dapat membuat satu-liner dengan menggunakan operator ternary .

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

Lihat kode ini berjalan langsung di IdeOne.com.

abcdefghi ...

Java stream

Fasilitas Java Streaming membuat ini menarik, seperti Java 9 dan yang lebih baru. Menarik, tapi mungkin bukan pendekatan terbaik.

Kami menggunakan poin kode daripada charnilai. The charjenis warisan, dan terbatas pada subset dari semua kemungkinan Unicode karakter.

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

Jika kami memiliki karakter berlebih terpotong, ganti karakter terakhir dengan elipsis .

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

Kalau saja saya bisa memikirkan cara untuk menyatukan garis aliran dengan bagian "jika melebihi batas, lakukan ellipsis".

Basil Bourque
sumber
Tidak. Jelas, dia ingin memotong panjang tali jika panjangnya mencapai 11 atau lebih. Anda harus mengerjakan sistem AI baru oO
JD333
1
@ JD333 Komentar Anda keluar dari saya. Memotong hingga 10 termasuk elipsis adalah persis apa yang saya tunjukkan di sini.
Basil Bourque
0
str==null ? str : str.substring(0, Math.min(str.length(), 10))

atau,

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

Bekerja dengan nol.

hal yang sama
sumber