Word wrap to X lines instead of maximum width (Least raggedness)

后端 未结 8 1755

Does anyone know a good algorithm to word wrap an input string to a specified number of lines rather than a set width. Basically to achieve the minimum width for X lines.

8条回答
  •  执笔经年
    2020-12-09 13:58

    I converted the C# accepted answer to JavaScript for something I was working on. Posting it here might save someone a few minutes of doing it themselves.

    function WrapTextWithLimit(text, n) {
        var words = text.toString().split(' ');
        var cumwordwidth = [0];
        words.forEach(function(word) {
            cumwordwidth.push(cumwordwidth[cumwordwidth.length - 1] + word.length);
        });
        var totalwidth = cumwordwidth[cumwordwidth.length - 1] + words.length - 1;
        var linewidth = (totalwidth - (n - 1.0)) / n;
        var cost = function(i, j) {
            var actuallinewidth = Math.max(j - i - 1, 0) + (cumwordwidth[j] - cumwordwidth[i]);
            return (linewidth - actuallinewidth) * (linewidth - actuallinewidth);
        };
        var best = [];
        var tmp = [];
        best.push(tmp);
        tmp.push([0.0, -1]);
        words.forEach(function(word) {
            tmp.push([Number.MAX_VALUE, -1]);
        });
        for (var l = 1; l < n + 1; ++l)
        {
            tmp = [];
            best.push(tmp);
            for (var j = 0; j < words.length + 1; ++j)
            {
                var min = [best[l - 1][0][0] + cost(0, j), 0];
                for (var k = 0; k < j + 1; ++k)
                {
                    var loc = best[l - 1][k][0] + cost(k, j);
                    if (loc < min[0] || (loc === min[0] && k < min[1])) {
                        min = [loc, k];
                    }
                }
                tmp.push(min);
            }
        }
        var lines = [];
        var b = words.length;
        for (var p = n; p > 0; --p) {
            var a = best[p][b][1];
            lines.push(words.slice(a, b).join(' '));
            b = a;
        }
        lines.reverse();
        return lines;
    }
    

提交回复
热议问题