Python memotong string panjang

245

Bagaimana cara memotong string hingga 75 karakter dalam Python?

Ini adalah bagaimana hal itu dilakukan dalam JavaScript:

var data="saddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsaddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsadddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
var info = (data.length > 75) ? data.substring[0,75] + '..' : data;
Hulk
sumber

Jawaban:

425
info = (data[:75] + '..') if len(data) > 75 else data
Marcelo Cantos
sumber
58
Saya akan mengubah kondisinya mungkin untuk len(data) > 77memperhitungkan titik ganda (tidak ada gunanya untuk memotong hanya karakter terakhir hanya untuk menggantinya dengan titik).
hasen
5
@ Hasenj: Itu tidak sesuai dengan kode asli, tapi itu saran yang bagus yang harus saya tunjukkan di tempat pertama.
Marcelo Cantos
2
Perhatikan bahwa parens yang disertakan tentu saja opsional.
Taylor Edmiston
10
@TaylorEdmiston Benar, tetapi mereka cukup membantu bagi mereka yang tidak mengingat semua aturan prioritas di 5–10 bahasa yang mereka gunakan setiap hari.
Marcelo Cantos
2
@Anthony a slice
Marcelo Cantos
126

Bahkan lebih pendek:

info = data[:75] + (data[75:] and '..')
stanlekub
sumber
2
Pendekatan lucu untuk melakukannya. Meskipun itu masih satu-liner komposit. ^^
Ceria
3
bukankah solusi ini memiliki 77 karakter jika Anda memasukkan '..'?
Mark Chackerian
bukankah ini melakukan dua operasi slice? Saya bertanya-tanya bagaimana kinerjanya dibandingkan dengan mengatakan stackoverflow.com/a/52279347/1834057 , ketika kinerjanya sangat penting
Nicholas Hamilton
1
Tentu, jawaban asli yang bagus, tetapi jawaban Marcelo lebih baik karena lebih eksplisit dan dengan demikian dapat dibaca (dan dengan demikian Pythonic).
sitnarf
114

Yang lebih ringkas:

data = data[:75]

Jika kurang dari 75 karakter tidak akan ada perubahan.

Neil
sumber
9
Mungkin dia ingin elips ditambahkan jika string terpotong.
FogleBird
4
Anda benar - saya tidak pernah memperhatikan itu. Saya tidak bisa memikirkan cara yang lebih baik untuk melakukan itu daripada jawaban lain.
neil
82

Jika Anda menggunakan Python 3.4+, Anda dapat menggunakan textwrap.shortendari pustaka standar:

Ciutkan dan potong teks yang diberikan agar sesuai dengan lebar yang diberikan.

Pertama spasi putih dalam teks diciutkan (semua spasi putih diganti dengan spasi tunggal). Jika hasilnya pas dengan lebar, itu dikembalikan. Kalau tidak, cukup kata-kata yang dijatuhkan dari ujung sehingga kata-kata yang tersisa ditambah placeholder pas dengan lebar:

>>> textwrap.shorten("Hello  world!", width=12)
'Hello world!'
>>> textwrap.shorten("Hello  world!", width=11)
'Hello [...]'
>>> textwrap.shorten("Hello world", width=10, placeholder="...")
'Hello...'
Bora M. Alper
sumber
8
Tampaknya celana panjangnya pada string yang sangat panjang (tanpa spasi) dan hanya menghasilkan elipsis.
elBradford
5
@elBradford (dan orang lain yang tertarik): itu karena shorten()memotong kata , bukan karakter tunggal. Saya mencari tetapi sepertinya tidak ada cara untuk mengkonfigurasi shorten()atau TextWrappercontoh untuk klip karakter tunggal dan bukan kata-kata.
Acsor
Dan itu memiliki efek samping yang mengganggu dari menghapus jeda baris
havlock
Ini tidak menyelesaikan pertanyaan OP. Ini terpotong oleh kata dan bahkan menghilangkan spasi.
Florian Wendelborn
9

Anda bisa menggunakan ini satu-liner:

data = (data[:75] + '..') if len(data) > 75 else data
phoenix24
sumber
2
apa yang [:n]disebut sehingga saya bisa mencarinya di dokumentasi?
oldboy
9

Dengan regex:

re.sub(r'^(.{75}).*$', '\g<1>...', data)

String panjang terpotong:

>>> data="11111111112222222222333333333344444444445555555555666666666677777777778888888888"
>>> re.sub(r'^(.{75}).*$', '\g<1>...', data)
'111111111122222222223333333333444444444455555555556666666666777777777788888...'

String yang lebih pendek tidak pernah terpotong:

>>> data="11111111112222222222333333"
>>> re.sub(r'^(.{75}).*$', '\g<1>...', data)
'11111111112222222222333333'

Dengan cara ini, Anda juga dapat "memotong" bagian tengah string, yang lebih bagus dalam beberapa kasus:

re.sub(r'^(.{5}).*(.{5})$', '\g<1>...\g<2>', data)

>>> data="11111111112222222222333333333344444444445555555555666666666677777777778888888888"
>>> re.sub(r'^(.{5}).*(.{5})$', '\g<1>...\g<2>', data)
'11111...88888'
Davide Guerri
sumber
baik itu tidak berfungsi ketika Anda memiliki spasi di string Anda
holms
Mengapa Anda menggunakan regex untuk kasus sederhana seperti itu?
Bora M. Alper
5

Metode ini tidak digunakan jika:

data[:75] + bool(data[75:]) * '..'

Sassan
sumber
4
Saya menulisnya hanya untuk menunjukkan bahwa itu mungkin. Ini bertentangan dengan filosofi keterbacaan python. Itu tidak memiliki keunggulan kinerja dibandingkan dengan metode berbasis "jika" lainnya. Saya tidak pernah menggunakannya dan saya tidak menyarankan Anda menggunakannya juga.
Sassan
4
limit = 75
info = data[:limit] + '..' * (len(data) > limit)
Halo selamat tinggal
sumber
1
Ini adalah solusi paling elegan. Selain itu saya akan mengekstrak batas karakter (dalam hal ini 75) menjadi variabel untuk menghindari ketidakkonsistenan. limit = 75; info = data[:limit] + '..' * (len(data) > limit)
ekauffmann
3

Namun solusi lain. Dengan Truedan FalseAnda mendapatkan sedikit umpan balik tentang tes di akhir.

data = {True: data[:75] + '..', False: data}[len(data) > 75]
Bugeater yang Benar
sumber
2

Ini hanya di:

n = 8
s = '123'
print  s[:n-3] + (s[n-3:], '...')[len(s) > n]
s = '12345678'
print  s[:n-3] + (s[n-3:], '...')[len(s) > n]
s = '123456789'     
print  s[:n-3] + (s[n-3:], '...')[len(s) > n]
s = '123456789012345'
print  s[:n-3] + (s[n-3:], '...')[len(s) > n]

123
12345678
12345...
12345...
dansalmo
sumber
Semua jawaban sebelumnya mengabaikan untuk mempertimbangkan apa yang benar-benar diinginkan OP - string keluaran tidak lebih dari 75 karakter. Kudos untuk memahami prinsip pemrograman "jangan lakukan apa yang saya katakan, lakukan apa yang saya inginkan". Untuk kelengkapan, Anda dapat memperbaiki kasing sudut n <3 dengan menambahkan: jika n> 2 s [: n]
Dave
1
       >>> info = lambda data: len(data)>10 and data[:10]+'...' or data
       >>> info('sdfsdfsdfsdfsdfsdfsdfsdfsdfsdfsdf')
           'sdfsdfsdfs...'
       >>> info('sdfsdf')
           'sdfsdf'
       >>> 
Spouk
sumber
1
Tolong jelaskan jawaban Anda?
Gwenc37
contoh serupa dari fungsi ini info info2 (data): jika len (data)> 10: return data [: 10] + '...' lain: kembalikan data instruksi lambda dari desain tanpa nama dengan gaya fungsional ex = lambda x: x + 1 ex ex (x): return x + 1
Spouk
1

Anda tidak dapat benar-benar "memotong" string Python seperti Anda dapat melakukan string C yang dialokasikan secara dinamis. String dalam Python tidak dapat diubah. Yang bisa Anda lakukan adalah mengiris string seperti yang dijelaskan dalam jawaban lain, menghasilkan string baru yang hanya berisi karakter yang ditentukan oleh offset irisan dan langkah. Dalam beberapa kasus (tidak praktis) ini bisa sedikit menjengkelkan, seperti ketika Anda memilih Python sebagai bahasa wawancara Anda dan pewawancara meminta Anda untuk menghapus karakter duplikat dari string di tempat. Doh.

Dave
sumber
1
info = data[:min(len(data), 75)
Jesse
sumber
Kode hanya jawaban yang umumnya dianggap berkualitas rendah. Bisakah Anda menambahkan penjelasan pada jawaban Anda.
Lemon Kazi
0

Tidak perlu untuk ekspresi reguler tetapi Anda ingin menggunakan pemformatan string daripada penggabungan string dalam jawaban yang diterima.

Ini mungkin cara Pythonic paling kanonik untuk memotong string datapada 75 karakter.

>>> data = "saddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsaddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsadddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
>>> info = "{}..".format(data[:75]) if len(data) > 75 else data
>>> info
'111111111122222222223333333333444444444455555555556666666666777777777788888...'
Adam Nelson
sumber
Saya merasa lucu bagaimana saddddddd...string Anda berubah menjadi 111111...:) Saya tahu ini adalah kesalahan ketik copy-paste, dan saya setuju dengan Anda tentang ekspresi reguler.
akarilimano
0

Inilah fungsi yang saya buat sebagai bagian dari kelas String baru ... Ini memungkinkan menambahkan akhiran (jika string berukuran setelah pemangkasan dan menambahkannya cukup lama - meskipun Anda tidak perlu memaksakan ukuran absolut)

Saya sedang dalam proses mengubah beberapa hal di sekitar sehingga ada beberapa biaya logika yang tidak berguna (jika _truncate ... misalnya) di mana itu tidak lagi diperlukan dan ada pengembalian di atas ...

Tapi, itu masih berfungsi baik untuk memotong data ...

##
## Truncate characters of a string after _len'nth char, if necessary... If _len is less than 0, don't truncate anything... Note: If you attach a suffix, and you enable absolute max length then the suffix length is subtracted from max length... Note: If the suffix length is longer than the output then no suffix is used...
##
## Usage: Where _text = 'Testing', _width = 4
##      _data = String.Truncate( _text, _width )                        == Test
##      _data = String.Truncate( _text, _width, '..', True )            == Te..
##
## Equivalent Alternates: Where _text = 'Testing', _width = 4
##      _data = String.SubStr( _text, 0, _width )                       == Test
##      _data = _text[  : _width ]                                      == Test
##      _data = ( _text )[  : _width ]                                  == Test
##
def Truncate( _text, _max_len = -1, _suffix = False, _absolute_max_len = True ):
    ## Length of the string we are considering for truncation
    _len            = len( _text )

    ## Whether or not we have to truncate
    _truncate       = ( False, True )[ _len > _max_len ]

    ## Note: If we don't need to truncate, there's no point in proceeding...
    if ( not _truncate ):
        return _text

    ## The suffix in string form
    _suffix_str     = ( '',  str( _suffix ) )[ _truncate and _suffix != False ]

    ## The suffix length
    _len_suffix     = len( _suffix_str )

    ## Whether or not we add the suffix
    _add_suffix     = ( False, True )[ _truncate and _suffix != False and _max_len > _len_suffix ]

    ## Suffix Offset
    _suffix_offset = _max_len - _len_suffix
    _suffix_offset  = ( _max_len, _suffix_offset )[ _add_suffix and _absolute_max_len != False and _suffix_offset > 0 ]

    ## The truncate point.... If not necessary, then length of string.. If necessary then the max length with or without subtracting the suffix length... Note: It may be easier ( less logic cost ) to simply add the suffix to the calculated point, then truncate - if point is negative then the suffix will be destroyed anyway.
    ## If we don't need to truncate, then the length is the length of the string.. If we do need to truncate, then the length depends on whether we add the suffix and offset the length of the suffix or not...
    _len_truncate   = ( _len, _max_len )[ _truncate ]
    _len_truncate   = ( _len_truncate, _max_len )[ _len_truncate <= _max_len ]

    ## If we add the suffix, add it... Suffix won't be added if the suffix is the same length as the text being output...
    if ( _add_suffix ):
        _text = _text[ 0 : _suffix_offset ] + _suffix_str + _text[ _suffix_offset: ]

    ## Return the text after truncating...
    return _text[ : _len_truncate ]
Acecool
sumber
1
bagaimana dengan semua garis bawah di setiap argumen dan variabel?
Nicholas Hamilton
0
info = data[:75] + ('..' if len(data) > 75 else '')
Halo selamat tinggal
sumber