web-dev-qa-db-ja.com

単語の途中で終わっていない文字列を切り詰める

私はPythonで文字列を切り捨てる方法を探しています。それは単語の途中で文字列を切り取らないでしょう。

例えば:

元:「これは本当に素晴らしいです。」
「ダム」は切り捨てます:「これは本当です...」
「スマート」は切り捨てます:「これは本当に...」 

私は上から「スマート」な切り捨てを達成する方法を探しています。

42
Jack

私は実際に私の最近のプロジェクトでこれに対する解決策を書きました。その大部分を少し小さく圧縮しました。

def smart_truncate(content, length=100, suffix='...'):
    if len(content) <= length:
        return content
    else:
        return ' '.join(content[:length+1].split(' ')[0:-1]) + suffix

何が起こるかは、コンテンツが既にカットオフポイントよりも小さいかどうかをifステートメントがチェックすることです。そうでない場合は、目的の長さに切り詰め、スペースで分割し、最後の要素を削除して(Wordを切り取らないように)、次に結合します( '...'をタックしながら) 。

61
Adam

Adamのソリューションの最後の行の少し良いバージョンを次に示します。

return content[:length].rsplit(' ', 1)[0]+suffix

(これは少し効率的で、文字列の前にスペースがない場合に、より適切な結果を返します。)

45
bobince

タブの処理(たとえば、それらを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()に渡すことで、他のいくつかのソリューションで使用されているソフト制限に変更できます。この場合、Word全体が返されます。この動作が必要な場合は、最後の行を次のように変更します。

    lines = textwrap.wrap(text, max_size-3, break_long_words=False)
    return lines[0] + ("..." if len(lines)>1 else "")

あなたが望む正確な振る舞いに応じて興味があるかもしれないexpand_tabsのような他のいくつかのオプションがあります。

11
Brian
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

OR

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)

OR

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
7
Markus Jarderot
>>> import textwrap
>>> textwrap.wrap('The quick brown fox jumps over the lazy dog', 12)
['The quick', 'brown fox', 'jumps over', 'the lazy dog']

あなたはその最初の要素を取り、完了しました...

6
Antonio
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...'
3
Vebjorn Ljosa

Python 3.4+から textwrap.shorten を使用できます。OPの例では:

>>> import textwrap
>>> original = "This is really awesome."
>>> textwrap.shorten(original, width=20, placeholder="...")
'This is really...'

textwrap.shorten(テキスト、幅、** kwargs)

指定された幅に収まるように、指定されたテキストを折りたたみ、切り捨てます。

最初に、テキストの空白が折りたたまれます(すべての空白は単一のスペースに置き換えられます)。結果が幅に収まる場合は、それが返されます。それ以外の場合は、残りの単語とプレースホルダーが幅内に収まるように、十分な単語が最後から削除されます。

1
marcanuy