2010-02-28 98 views
14

這裏是我寫的,打破了長串入行不大於給定長度長串插入換行符 - 自動換行

strBreakInLines <- function(s, breakAt=90, prepend="") { 
    words <- unlist(strsplit(s, " ")) 
    if (length(words)<2) return(s) 
    wordLen <- unlist(Map(nchar, words)) 
    lineLen <- wordLen[1] 
    res <- words[1] 
    lineBreak <- paste("\n", prepend, sep="") 
    for (i in 2:length(words)) { 
    lineLen <- lineLen+wordLen[i] 
    if (lineLen < breakAt) 
     res <- paste(res, words[i], sep=" ") 
    else { 
     res <- paste(res, words[i], sep=lineBreak) 
     lineLen <- 0 
    } 
    } 
    return(res) 
} 

它適用於我的問題不再是一個功能;但我想知道我能否在這裏學到一些東西。是否有更短或更有效的解決方案,特別是我可以擺脫for循環?

回答

35

如何:

gsub('(.{1,90})(\\s|$)', '\\1\n', s) 

這將打破串「S」與最多不超過90個字符線(不包括換行字符「\ n」,但包括字間空格),除非有一個詞本身超過90個字符,那麼這個詞本身將佔據整條線。

順便說一句,你的功能似乎打破---你應該更換

lineLen <- 0 

lineLen <- wordLen[i] 
+0

偉大的解決方案!我覺得我需要了解正則表達式,謝謝你指出我的函數中的錯誤。 – 2010-02-28 18:53:48

+0

你能否添加一個註釋來解釋每個部件具體做什麼? – theforestecologist 2017-01-21 23:59:44

3

你可以看一下例如R本身的write.dcf()函數;它也使用一個循環,所以沒有什麼可以在這裏感到羞恥。

第一個目標是得到它的權利---看到錢伯斯(2008)。

+2

檢查write.dcf(然後formatDL)提出了功能strwrap這不正是我的職責嘗試這樣做。 – 2010-02-28 19:03:59

+0

完美 - 我知道有一些東西,但我沒有立即找到它。我需要這一次,小紅莓,以及... – 2010-02-28 19:06:34

15

爲了完整起見,在strwrap卡斯滕W.的評論點,這是最簡單的功能要記住:

strwrap("Lorem ipsum... you know the routine", width=10) 

和精確匹配的問題提出的解決方案,該字符串必須在事後粘貼:

paste(strwrap(s,90), collapse="\n") 

這個帖子故意製造社會的維基,因爲找到函數的榮譽不是我的。

+0

如果您需要將此作爲一個函數,你也可以修改'strwrap'在'sapply'以下用戶定義的公式: '微調< - 功能(X,break_limit) { sapply(strwrap(X,break_limit,簡化= FALSE),糊,崩= 「\ n」 個) }' – 2016-08-04 19:50:21

6

爲了進一步完整,有:

  • stringi::stri_wrap
  • stringr::str_wrap(這只是最終調用stringi::stri_wrap

stringi版本將處理的字符集更好(這是建立在ICU庫),它的C/C++版本最終會比base::strwrap更快,它也是矢量化的參數str