44

単語の途中で文字列を切り捨てない Python で文字列を切り捨てる方法を探しています。

例えば:

原文:「これは本当に素晴らしいです。」
「ばかげた」切り捨て:「これは本当です...」
「スマート」切り捨て:「これは本当に...」

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

4

10 に答える 10

66

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

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

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

于 2008-10-30T14:36:03.550 に答える
48

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

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

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

于 2008-10-30T14:43:16.343 に答える
11

タブの処理 (たとえば、タブを 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 のような他のオプションがいくつかあります。

于 2008-10-30T15:47:04.547 に答える
9
>>> import textwrap
>>> textwrap.wrap('The quick brown fox jumps over the lazy dog', 12)
['The quick', 'brown fox', 'jumps over', 'the lazy dog']

その最初の要素を取得するだけで完了です...

于 2013-12-29T02:54:59.890 に答える
9
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
于 2008-10-30T14:59:41.363 に答える
3
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...'
于 2008-10-30T14:44:05.170 に答える
0

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;    
}
于 2021-12-28T20:12:57.553 に答える
0

単語単位ではなく完全な文単位で切り捨てたい場合は、次の手順から始めてください。

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))
于 2021-01-21T22:26:32.093 に答える