単語の途中で文字列を切り捨てない Python で文字列を切り捨てる方法を探しています。
例えば:
原文:「これは本当に素晴らしいです。」 「ばかげた」切り捨て:「これは本当です...」 「スマート」切り捨て:「これは本当に...」
上から「スマート」な切り捨てを達成する方法を探しています。
私は実際に私の最近のプロジェクトでこれに対する解決策を書きました。私はそれの大部分を少し小さくするために圧縮しました。
def smart_truncate(content, length=100, suffix='...'):
if len(content) <= length:
return content
else:
return ' '.join(content[:length+1].split(' ')[0:-1]) + suffix
何が起こるかというと、ifステートメントはコンテンツがすでにカットオフポイントを下回っているかどうかをチェックします。そうでない場合は、目的の長さに切り詰め、スペースで分割し、最後の要素を削除して(単語を切り落とさないように)、次にそれを結合します(「...」をタックしながら) 。
Adamのソリューションの最後の行の少し良いバージョンを次に示します。
return content[:length].rsplit(' ', 1)[0]+suffix
(これは少し効率的で、文字列の前にスペースがない場合に、より賢明な結果を返します。)
タブの処理 (たとえば、タブを 8 つのスペースとして表示しているが、内部では 1 文字として扱っている場合)、さまざまなフレーバーの改行および非空白を分割したり、ハイフネーションなどで分割できるようにしたりします。これらのいずれかが望ましい場合は、textwrap モジュールを調べてください。例えば:
def truncate(text, max_size):
if len(text) <= max_size:
return text
return textwrap.wrap(text, max_size-3)[0] + "..."
max_size より大きい単語のデフォルトの動作は、それらを破ることです (max_size をハード リミットにします)。break_long_words=False を wrap() に渡すことで、他のソリューションで使用されているソフト リミットに変更できます。この場合、単語全体が返されます。この動作が必要な場合は、最後の行を次のように変更します。
lines = textwrap.wrap(text, max_size-3, break_long_words=False)
return lines[0] + ("..." if len(lines)>1 else "")
必要な正確な動作に応じて、expand_tabs のような他のオプションがいくつかあります。
>>> import textwrap
>>> textwrap.wrap('The quick brown fox jumps over the lazy dog', 12)
['The quick', 'brown fox', 'jumps over', 'the lazy dog']
その最初の要素を取得するだけで完了です...
def smart_truncate1(text, max_length=100, suffix='...'):
"""Returns a string of at most `max_length` characters, cutting
only at word-boundaries. If the string was truncated, `suffix`
will be appended.
"""
if len(text) > max_length:
pattern = r'^(.{0,%d}\S)\s.*' % (max_length-len(suffix)-1)
return re.sub(pattern, r'\1' + suffix, text)
else:
return text
また
def smart_truncate2(text, min_length=100, suffix='...'):
"""If the `text` is more than `min_length` characters long,
it will be cut at the next word-boundary and `suffix`will
be appended.
"""
pattern = r'^(.{%d,}?\S)\s.*' % (min_length-1)
return re.sub(pattern, r'\1' + suffix, text)
また
def smart_truncate3(text, length=100, suffix='...'):
"""Truncates `text`, on a word boundary, as close to
the target length it can come.
"""
slen = len(suffix)
pattern = r'^(.{0,%d}\S)\s+\S+' % (length-slen-1)
if len(text) > length:
match = re.match(pattern, text)
if match:
length0 = match.end(0)
length1 = match.end(1)
if abs(length0+slen-length) < abs(length1+slen-length):
return match.group(0) + suffix
else:
return match.group(1) + suffix
return text
def smart_truncate(s, width):
if s[width].isspace():
return s[0:width];
else:
return s[0:width].rsplit(None, 1)[0]
テスト:
>>> smart_truncate('The quick brown fox jumped over the lazy dog.', 23) + "..."
'The quick brown fox...'
C++ バージョン:
string trim(string s, int k) {
if (s.size()<=k) return s;
while(k>=0 && s[k]!=' ')
k--;
if (k<0) return "";
string res=s.substr(0, k+1);
while(res.size() && (res.back()==' '))
res.pop_back();
return res;
}
単語単位ではなく完全な文単位で切り捨てたい場合は、次の手順から始めてください。
def smart_truncate_by_sentence(content, length=100, suffix='...',):
if not isinstance(content,str): return content
if len(content) <= length:
return content
else:
sentences=content.split('.')
cs=np.cumsum([len(s) for s in sentences])
n = max(1, len(cs[cs<length]) )
return '.'.join(sentences[:n])+ '. ...'*(n<len(sentences))