简体   繁体   English

在长字符串中插入换行符 - 自动换行

[英]Insert line breaks in long string — word wrap

Here is a function I wrote to break a long string into lines not longer than a given length 这是我写的一个函数,用于将长字符串分成不长于给定长度的行

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)
}

It works for the problem I had; 它适用于我遇到的问题; but I wonder if I can learn something here. 但我想知道我是否可以在这里学到一些东西。 Is there a shorter or more efficient solution, especially can I get rid of the for loop? 是否有更短或更有效的解决方案,尤其是我可以摆脱for循环?

How about this: 这个怎么样:

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

It will break string "s" into lines with maximum 90 chars (excluding the line break character "\\n", but including inter-word spaces), unless there is a word itself exceeding 90 chars, then that word itself will occupy a whole line. 它会将字符串“s”分成最多90个字符的行(不包括换行符“\\ n”,但包括字间空格),除非有一个字本身超过90个字符,那么该字本身将占用一个整体线。

By the way, your function seems broken --- you should replace 顺便说一下,你的功能似乎已经破碎了 - 你应该更换

lineLen <- 0

with

lineLen <- wordLen[i]

For the sake of completeness, Karsten W.'s comment points at strwrap , which is the easiest function to remember: 为了完整起见,Karsten W.的评论指出了strwrap ,这是最容易记住的功能:

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

and to match exactly the solution proposed in the question, the string has to be pasted afterwards: 并且要完全匹配问题中提出的解决方案,之后必须粘贴字符串:

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

This post is deliberately made community wiki since the honor of finding the function isn't mine. 这篇文章是故意制作社区维基,因为找到该功能的荣誉不是我的。

For further completeness, there's: 为了进一步完整,有:

  • stringi::stri_wrap
  • stringr::str_wrap (which just ultimately calls stringi::stri_wrap stringr::str_wrap (最终调用stringi::stri_wrap

The stringi version will deal with character sets better (it's built on the ICU library) and it's in C/C++ so it'll ultimately be faster than base::strwrap . stringi版本将更好地处理字符集(它建立在ICU库上)并且它在C / C ++中,所以它最终会比base::strwrap更快。 It's also vectorized over the str parameter. 它也在str参数上进行了矢量化。

You can look at eg the write.dcf() FUNCTION in R itself; 您可以查看例如R本身中的write.dcf() FUNCTION; it also uses a loop so nothing to be ashamed of here. 它也使用循环,所以没有什么可以在这里感到羞耻。

The first goal is to get it right --- see Chambers (2008). 第一个目标是让它正确 - 见Chambers(2008)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM