2008-12-30 26 views
7

比方說,我已經爲我工作的公司編寫了自定義電子郵件管理應用程序。它從該公司的支持賬戶讀取電子郵件,並將清理後的純文本版本存儲在數據庫中,執行其他整潔的事情,例如將其與客戶賬戶和訂單進行關聯。當員工回覆郵件時,我的程序將生成一封電子郵件,該郵件以討論話題的格式化版本發送給客戶。如果客戶作出響應,應用程序會在主題行中查找唯一編號以讀取傳入消息,刪除先前的討論,並將其作爲線程中的新項目添加。例如:重新包裝硬包裝文本的算法?

 
This is a message from Contoso customer service. 

Recently, you requested customer support. Below is a summary of your 
request and our reply. 

-------------------------------------------------------------------- 
Contoso (Fred) on Tuesday, December 30, 2008 at 9:04 a.m. 
-------------------------------------------------------------------- 
John: 

I've modified your address. You can confirm my work by logging into 
"Your Account" on our Web site. Your order should ship out today. 

Thanks for shopping at Contoso. 

-------------------------------------------------------------------- 
You on Tuesday, December 30, 2008 at 8:03 a.m. 
-------------------------------------------------------------------- 
Oops, I entered my address incorrectly. Can you change it to 

Fred Smith 
123 Main St 
Anytown, VA 12345 

Thanks! 

-- 
Fred Smith 
Contoso Product Lover 

一般情況下,這一切的偉大工程,但有一個領域,我已經種推遲,現在清理了一段時間,並與文字環繞交易。爲了生成如上所述的漂亮的電子郵件格式,我需要重新包裝客戶最初發送的文本。

我已經寫了一個算法來做到這一點(雖然看代碼,我不完全確定它是如何工作的 - 它可以使用一些重構)。 但它無法區分硬覆蓋換行符,「換行符」換行符和「語義」換行符。例如,硬覆蓋換行符是電子郵件客戶端插入段落中以包裝長行文本(例如79列)的換行符。段落換行符的結尾是用戶在段落中的最後一句之後添加的結尾。而語義換行符就像br標籤,比如Fred上面輸入的地址。

我的算法,而不是隻看到兩個新行連續爲表明一個新的段落,所以它將使客戶的電子郵件進行格式化類似如下:

 
Oops, I entered my address incorrectly. Can you change it to 

Fred Smith 123 Main St Anytown, VA 12345 

Thanks! 

-- Fred Smith Contoso Product Lover 

每當我試着寫一個版本這將重新包裝這個文本的意圖,我基本上打了一個牆,因爲我需要知道文本的語義,「硬包裝」換行符和「我真的這意味着它像一個br」類型之間的區別換行符,例如在客戶的地址中。 (我連續使用兩條換行符來確定何時開始一個新段落,這與大多數人似乎實際鍵入電子郵件的方式一致。)

任何人都有一種算法,可以將文本重新包裝爲意?或者當衡量任何給定解決方案的複雜性時,這個實現是否「足夠好」?

謝謝。

回答

3

您可以嘗試檢查是否插入了換行符以將行長度保持在最大值以下(又名硬包裝):只需檢查文本中最長的行。然後,對於任何給定的行,您將以下行的第一個單詞追加到它。如果結果行超過最大長度,換行符可能是硬包裝。

更簡單的你可能會認爲(maxlength - 15) <= length <= maxlength的所有休息都是硬包(15只是一個受過教育的猜測)。這肯定會過濾掉地址和內容中的故意中斷,而且在此範圍內的任何錯過的中斷都不會對結果造成太大影響。

+0

感謝您的這個簡單的想法。看到我的答案下面的快速和髒樣本實施。 – 2008-12-30 19:44:44

2

我有兩個建議,如下所示。

  • 注重標點符號:這將幫助你以一個「硬包裝」換行和換行符(「段落的結束」之間的區別,因爲,如果該行以句號結束,那麼它更可能用戶希望它成爲段落的尾部。

  • 請注意線條是否比最大線條長度短得多:在上例中,您可能有79個字符的「硬包裝」文本,並且地址線只有30個字符長;由於30遠小於79,因此您知道地址線被用戶打破,而不是用戶的文本包裝算法。

此外,要注意縮進:這是從左邊縮進空白線可以被認爲是新的段落,從以前的線路壞了,因爲他們在這個論壇。

2

按照上面的Ole的建議,我重新執行了我的實現來查看一個閾值。它似乎處理大多數情況下,我扔在它沒有我不得不瘋狂和編寫實際上理解英語的代碼。

基本上,我首先掃描輸入字符串,並在變量inputMaxLineLength中記錄最長的行長度。然後,當我重新包裝時,如果我遇到一個索引號在inputMaxLineLengthinputMaxLineLength的85%之間的換行符,那麼我用空格替換該換行符,因爲我認爲這是一個硬換行換行符 - 除非緊接着是另一個換行符,因爲那時我認爲這只是一個恰好在該範圍內的單行段落。例如,如果某人輸入了一個簡短的項目符號列表,就會發生這種情況。

當然,這並不完美,但對於我的場景來說,「足夠好」,考慮到文本通常會被以前的電子郵件客戶端所損壞。下面是一些代碼,我的一個幾個小時的實現可能仍然在少數邊緣案例中使用C#)。這比我以前的解決方案複雜得多,這很好。

Source Code

而且這裏的一些單元測試,行使代碼(使用MSTest的):

Test Code

如果任何人有一個更好的實現(和無疑是一個更好的實現存在),我我會很高興看到你的想法!謝謝。