【问题标题】:Add a separator between every element of a string在字符串的每个元素之间添加分隔符
【发布时间】:2019-10-29 23:45:07
【问题描述】:

假设这样一个字符串向量:

x <- c("abc", "abcde", "abcde123")

我想在给定字符串的每个元素之间添加一个分隔符(逗号或其他)以实现类似的效果(此处分隔符是逗号):

[1] "a,b,c"           "a,b,c,d,e"       "a,b,c,d,e,1,2,3"

我可以通过以下方式实现它:

sapply(strsplit(x, "", fixed = TRUE), function(x) paste(x, collapse = ","))

但是,我很好奇是否有不同的方法来实现它。

【问题讨论】:

  • 没有通用函数的较短版本:sapply(strsplit(x, ""), paste, collapse=",").
  • 我已经回答了上述问题,但想知道您为什么需要这个。
  • 在这种情况下,您可以这样做:data.frame(X = "abc") %&gt;% separate(X, into = c("A", "B", "C"), sep = "\\B")
  • 或试试这个:data.frame(X = "abc") %&gt;% separate(X, into = c("A", "B", "C"), sep = 1:3)
  • @G.Grothendieck 也许将两个separate 替代品(和其他?)添加到Separate a column into multiple columns using tidyr::separate with sep=“” 干杯。

标签: r string


【解决方案1】:

它有什么问题?您可以利用 paste 已矢量化这一事实并跳过 funcioning。

sapply(strsplit(x, ""), paste, collapse=",")
# [1] "a,b,c"           "a,b,c,d,e"       "a,b,c,d,e,1,2,3"

您也可以使用gregexpr(灵感来自@Rich Scriven)。

sapply(regmatches(x, gregexpr(".", x)), paste, collapse=",")
# [1] "a,b,c"           "a,b,c,d,e"       "a,b,c,d,e,1,2,3"

【讨论】:

    【解决方案2】:

    1) 使用零宽度匹配 这两个 (...) 分别匹配我们想要逗号的前后的一个字符,但它们是零宽度,因为它们不消耗任何字符。

    gsub("(?<=.)(?=.)", ",", x, perl = TRUE)
    ## [1] "a,b,c"           "a,b,c,d,e"       "a,b,c,d,e,1,2,3"
    

    1a) 这也有效。这里我们匹配一个字符和一个不消耗的后续字符,并将其替换为匹配的字符和一个逗号。

    gsub("(.)(?=.)", "\\1,", x, perl = TRUE)
    ## [1] "a,b,c"           "a,b,c,d,e"       "a,b,c,d,e,1,2,3"
    

    2) 插入和修剪 另一种方法是用逗号替换边界,然后修剪掉开头和结尾的逗号。这个不需要 perl 正则表达式。确保不要使用 perl=TRUE 。它对待 \b 的方式不同。

    gsub("^,|,$", "", gsub("\\b", ",", x))
    ## [1] "a,b,c"           "a,b,c,d,e"       "a,b,c,d,e,1,2,3"
    

    \\K 也可以使用perl = TRUE 代替\\b

    2a) 在 R 3.6(但不是更早版本)中,trimws 有一个允许修剪任意字符的参数,因此可以简化为:

    trimws(gsub("\\b", ",", x), whitespace = ",")
    ## [1] "a,b,c"           "a,b,c,d,e"       "a,b,c,d,e,1,2,3"
    

    2b) 这种变体甚至在 3.6 之前也有效,但假设字符串中没有制表符。它用一个制表符替换每个边界,从末端修剪空白,然后用逗号替换制表符。

    chartr("\t", ",", trimws(gsub("\\b", "\t", x)))
    ## [1] "a,b,c"           "a,b,c,d,e"       "a,b,c,d,e,1,2,3"
    

    2c) 从问题下的讨论看来,逗号只是一个例子,就发帖者而言,空格也一样好。在这种情况下,我们可以将其简化为:

    trimws(gsub("\\b", " ", x))
    ## [1] "a b c"           "a b c d e"       "a b c d e 1 2 3"
    

    3) \B 像这样用逗号替换非边界。请务必指定 perl 正则表达式。如果字符串包含字母数字,这将起作用,但如果它们包含非单词字符,则不会。

    gsub("\\B", ",", x, perl = TRUE)
    ## [1] "a,b,c"           "a,b,c,d,e"       "a,b,c,d,e,1,2,3"
    

    【讨论】:

    • 涉及trimws() 的可能性非常好,因为它还显示了其中的新参数whitespace。谢谢你:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-21
    • 1970-01-01
    • 1970-01-01
    • 2012-12-06
    • 2019-04-05
    • 2023-02-25
    • 2021-08-02
    相关资源
    最近更新 更多