2010-02-28 94 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