7

假设我为我工作的公司编写了一个自定义电子邮件管理应用程序。它从公司的支持帐户中读取电子邮件,并将其清理后的纯文本版本存储在数据库中,并在此过程中执行其他简洁的操作,例如将其与客户帐户和订单相关联。当员工回复消息时,我的程序会生成一封电子邮件,该电子邮件将与讨论线程的格式化版本一起发送给客户。如果客户做出回应,应用程序会在主题行中查找唯一编号以读取传入消息,删除之前的讨论,并将其作为新项目添加到线程中。例如:

这是来自 Contoso 客户服务的消息。

最近,您请求客户支持。以下是您的摘要
请求和我们的答复。

-------------------------------------------------- ------------------
Contoso (Fred) 于 2008 年 12 月 30 日星期二上午 9:04
-------------------------------------------------- ------------------
约翰:

我已经修改了你的地址。您可以通过登录来确认我的工作
我们网站上的“您的帐户”。您的订单应该今天发货。

感谢您在 Contoso 购物。

-------------------------------------------------- ------------------
您于 2008 年 12 月 30 日星期二上午 8:03
-------------------------------------------------- ------------------
糟糕,我输入了错误的地址。你能把它改成

弗雷德·史密斯
主街 123 号
弗吉尼亚州任何镇 12345

谢谢!

--
弗雷德·史密斯
Contoso 产品爱好者

一般来说,这一切都很好,但有一个领域我现在有点推迟清理,它处理文本换行。为了生成像上面这样漂亮的电子邮件格式,我需要重新包装客户最初发送的文本。

我已经编写了一个算法来执行此操作(尽管查看代码,我并不完全确定它是如何工作的——它可以使用一些重构)。但它无法区分硬换行换行、“段落结尾”换行和“语义”换行。例如,硬换行换行是电子邮件客户端在段落中插入的换行,以换行一长行文本,例如 79 列。段落结尾换行符是用户在段落最后一句之后添加的换行符。语义换行符类似于br标签,例如 Fred 在上面键入的地址。

相反,我的算法只看到一行中的两个换行符表示一个新段落,因此它会使客户的电子邮件格式如下:

糟糕,我输入了错误的地址。你能把它改成

弗雷德·史密斯 123 Main St Anytown, VA 12345

谢谢!

-- Fred Smith Contoso 产品爱好者

每当我尝试编写一个可以按预期重新换行该文本的版本时,我基本上都会碰壁,因为我需要知道文本的语义,“硬换行”换行符和“我的意思是它就像一个br"-type 换行符,例如在客户的地址中。(我连续使用两个换行符来确定何时开始一个新段落,这与大多数人似乎实际键入电子邮件的方式一致。)

任何人都有可以按预期重新包装文本的算法?或者在权衡任何给定解决方案的复杂性时,这种实现是否“足够好”?

谢谢。

4

3 回答 3

3

您可以尝试检查是否已插入换行符以将行长度保持在最大值以下(也称为硬换行):只需检查文本中最长的行。然后,对于任何给定的行,将下一行的第一个单词附加到它。如果结果行超过最大长度,则换行符可能是硬换行。

更简单的是,您可能只是将所有(maxlength - 15) <= length <= maxlength闯入视为硬包装(15 只是有根据的猜测)。这肯定会过滤掉地址和内容中的故意中断,并且在此范围内任何错过的中断都不会对结果造成太大影响。

于 2008-12-30T14:29:16.830 回答
2

我有两个建议,如下。

  • 注意标点符号:这将帮助您区分“硬换行”换行符和“段落结尾”换行符(因为,如果该行以句号结尾,则更有可能是用户想要的一个段落的结尾。

  • 注意一行是否比最大行长短得多:在上面的示例中,您可能有 79 个字符的文本被“硬换行”,而且您的地址行只有 30 个字符长;因为 30 远小于 79,所以您知道地址行是由用户破坏的,而不是由用户的文本换行算法破坏的。

另外,请注意缩进:从左侧缩进空格的行可能被认为是新段落,与之前的行不同,就像在这个论坛上一样。

于 2008-12-30T14:59:16.863 回答
2

按照上面 Ole 的建议,我重新设计了实现以查看阈值。它似乎可以很好地处理我抛出的大多数场景,而无需我发疯并编写真正理解英语的代码。

基本上,我首先扫描输入字符串并在变量中记录最长的行长度inputMaxLineLength。然后当我重新包装时,如果我遇到一个索引在inputMaxLineLength85%之间的换行符inputMaxLineLength,那么我用一个空格替换那个换行符,因为我认为它是一个硬换行换行符——除非它后面紧跟着另一个换行符,因为那时我假设它只是一个恰好在该范围内的单行段落。例如,如果有人键入一个简短的项目符号列表,就会发生这种情况。

当然不是完美的,但对于我的场景来说“足够好”,考虑到文本通常一开始就被以前的电子邮件客户端破坏了一半。

这是一些代码,我的几个小时前的实现可能仍然在一些边缘情况下(使用 C#)。它比我以前的解决方案简单得多,这很好。

源代码

下面是一些执行该代码的单元测试(使用 MSTest):

测试代码

如果有人有更好的实现(毫无疑问存在更好的实现),我很乐意阅读您的想法!谢谢。

于 2008-12-30T19:43:53.873 回答