用省略号截断字符串的理想方法

2022-08-31 15:59:01

我相信我们所有人都在Facebook状态(或其他地方)上看到省略号,然后单击“显示更多”,只有另外2个字符左右。我想这是因为懒惰编程,因为肯定有一个理想的方法。

我的将苗条字符视为“半字符”,但是当省略号几乎隐藏任何字符时,这并不能解决省略号看起来很愚蠢。[iIl1]

有没有理想的方法?这是我的:

/**
 * Return a string with a maximum length of <code>length</code> characters.
 * If there are more than <code>length</code> characters, then string ends with an ellipsis ("...").
 *
 * @param text
 * @param length
 * @return
 */
public static String ellipsis(final String text, int length)
{
    // The letters [iIl1] are slim enough to only count as half a character.
    length += Math.ceil(text.replaceAll("[^iIl]", "").length() / 2.0d);

    if (text.length() > length)
    {
        return text.substring(0, length - 3) + "...";
    }

    return text;
}

语言并不重要,但被标记为Java,因为这是我最感兴趣的。


答案 1

我喜欢让“瘦”字符算作半个字符的想法。简单且近似。

然而,大多数省略号的主要问题是(恕我直言)它们在中间砍掉了单词。这是一个考虑单词边界的解决方案(但没有深入研究像素数学和Swing-API)。

private final static String NON_THIN = "[^iIl1\\.,']";

private static int textWidth(String str) {
    return (int) (str.length() - str.replaceAll(NON_THIN, "").length() / 2);
}

public static String ellipsize(String text, int max) {

    if (textWidth(text) <= max)
        return text;

    // Start by chopping off at the word before max
    // This is an over-approximation due to thin-characters...
    int end = text.lastIndexOf(' ', max - 3);

    // Just one long word. Chop it off.
    if (end == -1)
        return text.substring(0, max-3) + "...";

    // Step forward as long as textWidth allows.
    int newEnd = end;
    do {
        end = newEnd;
        newEnd = text.indexOf(' ', end + 1);

        // No more spaces.
        if (newEnd == -1)
            newEnd = text.length();

    } while (textWidth(text.substring(0, newEnd) + "...") < max);

    return text.substring(0, end) + "...";
}

算法的测试如下所示:

enter image description here


答案 2

我很震惊没有人提到Commons Lang StringUtils#abbreviate()

更新:是的,它没有考虑瘦字符,但我不同意考虑到每个人都有不同的屏幕和字体设置,并且登陆此页面的很大一部分人可能正在寻找像上面这样的维护库。


推荐