线包裹算法:贪婪的方法

时间:2015-02-21 06:26:16

标签: algorithm word-wrap linewrap

我需要一个简单的换行算法,所以我转向维基百科:

http://en.wikipedia.org/wiki/Line_wrap_and_word_wrap#Minimum_number_of_lines

贪心算法:

1. |  SpaceLeft := LineWidth
2. |  for each Word in Text
3. |      if (Width(Word) + SpaceWidth) > SpaceLeft
4. |         insert line break before Word in Text
5. |         SpaceLeft := LineWidth - Width(Word)
6. |      else
7. |         SpaceLeft := SpaceLeft - (Width(Word) + SpaceWidth)

在第5行,当我们开始一个新行并从可用宽度中减去字宽时,不应该减去空间宽度吗?

5. |         SpaceLeft := LineWidth - (Width(Word) + SpaceWidth)

为什么第5行没有考虑空间宽度?

- 更新 -

一些简单的测试。

在每个图像中,第一段由JavaScript使用上述包装算法(橙色轮廓)创建,第二段由浏览器本地呈现(蓝色轮廓)。 < / p>

有趣的是,这种非常简单的算法确实产生与浏览器渲染完全相同的结果,用于没有边缘情况的文本。

第一张图片显示我们使用时

SpaceLeft := LineWidth - Width(Word)

JS渲染和浏览器渲染完全相同。

但是下面的图片(不同的线宽)显示了我们使用时JS和浏览器渲染之间的细微差别:

SpaceLeft := LineWidth - (Width(Word) + SpaceWidth)

守则


// function getWidth() uses canvas to calculate the widths
// http://stackoverflow.com/questions/118241/calculate-text-width-with-javascript

var wrap = function(container, text, lineWidth) {
        var words = text.split(' ');
        var w, x, i, l;
        var spaceWidth = getWidth(' ');
        var spaceLeft = lineWidth;

        var arr = [], line = [];
        arr.push(line);

        for ( i = 0, l = words.length; i < l; i++ ) {
            w = words[i];
            x = getWidth(w) + spaceWidth;

            if ( x > spaceLeft ) {
                line = [];
                arr.push(line);
                line.push(w);

                // this is the case for Wikipedia algorithm
                // spaceLeft = lineWidth - getWidth(w);

                spaceLeft = lineWidth - x;
            }
            else {
                spaceLeft = spaceLeft - x;
                line.push(w);
            }
        }

        for ( i = 0, l = arr.length; i < l; i++ ) {

            container.append(
                $('<span>').text(arr[i].join(' '))
            );
        }
    };

1 个答案:

答案 0 :(得分:0)

该算法可能会更多&#34;更多&#34;如果第5行是

,请更正
5. |         SpaceLeft := LineWidth - (Width(Word) + SpaceWidth)

正如你的建议。

在任何情况下,问题都有点哲学,因为算法对于任何具体实现来说都太简单了,考虑到真正的实现需要注意文本可能已经包含新行的事实,这些词是不一定用空格(例如连字符)和/或多个空格分隔。

使用现有的实施可能是最好的解决方案,例如for Java:Wrap the string after a number of characters word-wise in Java