【问题标题】:R: Using paste depending on the number of words in a string within a functionR:根据函数内字符串中的单词数使用粘贴
【发布时间】:2015-05-25 14:07:10
【问题描述】:

我有一个列表,其中每个列表组件都有一个字符串向量。每个字符串向量的长度为 1,包含一个或多个用空格分隔的单词(原始列表要大得多):

> f <- list("one", "two three", "four", "five six seven")
> f
[[1]]
[1] "one"

[[2]]
[1] "two three"

[[3]]
[1] "four"

[[4]]
[1] "five six seven"

我需要做的是在每个组件中的字符串之前和之后粘贴字符串,具体取决于它是否包含一个或多个单词。我寻找的结果是这样的:

[[1]]
[1] "Single number: one."

[[2]]
[1] "Multiple numbers: two three."

[[3]]
[1] "Single number: four."

[[4]]
[1] "Multiple numbers: five six seven."

我尝试了以下方法,用stringr 包中的str_count 计算每个字符串中的单词数:

x <- lapply(f, function(j) {
  if(str_count(string = f[[j]], pattern = "\\S+") == 1) {
    xx[[j]] <- paste("Single number: ", f[[j]], ".", sep = "")
  } else {
    xx[[j]] <- paste("Multiple numbers: ", f[[j]], ".", sep = "")
  }
  })

但是,我收到以下错误:

Error in if (str_count(string = f[[j]], pattern = "\\S+") == 1) { : 
  argument is of length zero

有人可以帮忙吗?

【问题讨论】:

    标签: r string conditional-statements paste


    【解决方案1】:

    给定一个字符串,函数prefix 生成"Multiple number:""Single Number:"lapply 将其粘贴到f 的每个组件中,然后使用Map 将相应的前缀和f 组件粘贴在一起。没有使用任何包:

    prefix <- function(x) if (any(grepl(" ", x))) "Multiple numbers:" else "Single number:"
    Map(paste, lapply(f, prefix), f)
    

    给予:

    [[1]]
    [1] "Single number: one"
    
    [[2]]
    [1] "Multiple numbers: two three"
    
    [[3]]
    [1] "Single number: four"
    
    [[4]]
    [1] "Multiple numbers: five six seven"
    

    最后一行也可以这样写:

    as.list(paste(sapply(f, prefix), f))
    

    如果结果是一个列表并不重要,那么可以省略as.list

    【讨论】:

    • 非常感谢!简单高效的解决方案。
    【解决方案2】:

    f[[j]] 可以在我们索引列表的元素时使用,即lapply(seq_along(f),..,但这里我们循环的是f 本身。所以,就做str_count(j,..)

    library(stringr)
    lapply(f, function(j) {
                            if(str_count(j, '\\S+') >1) {
                                paste("Multiple numbers: ", j, '.', sep="") 
                              } else paste("Single number: ", j, ".", sep="") 
                           })
    #[[1]]
    #[1] "Single number: one."
    
    #[[2]]
    #[1] "Multiple numbers: two three."
    
    #[[3]]
    #[1] "Single number: four."
    
    #[[4]]
    #[1] "Multiple numbers: five six seven."
    

    注意:这也可以在不使用任何外部包的情况下完成。

    【讨论】:

    • 非常感谢!仍然对函数中的索引感到困惑。
    • @panman 可以看看lapply(seq_along(f), function(i) i)lapply(f, function(x) x)的输出`
    • 如果我理解正确,您指向的第一个解决方案返回列表组件序列的数字索引,而第二个返回组件本身。我今天学到了很多新东西:)
    • @panman 是的,你是对的。在您的帖子中,您尝试使用列表元素本身(即字符)来索引列表组件。
    • 我明白了。还处于起步阶段。非常感谢您为我澄清这些。
    【解决方案3】:

    您可以利用 R 的矢量化来简化这一点;但是,这需要使用 vector 作为输入而不是列表——这在您的示例中是可以的:

    f = unlist(f)
    prefix = ifelse(str_count(f, '\\S+') > 1, 'Multiple words: ', 'Single word: ')
    paste0(prefix, f, '.')
    

    【讨论】:

    • 谢谢!肯定会在其他情况下使用它。
    猜你喜欢
    • 2018-07-16
    • 2020-11-15
    • 1970-01-01
    • 2016-02-21
    • 2018-05-01
    • 2015-07-19
    • 1970-01-01
    • 2021-11-26
    • 2017-12-18
    相关资源
    最近更新 更多