【问题标题】:Split and re-concatenate a string拆分并重新连接字符串
【发布时间】:2018-07-20 17:51:01
【问题描述】:

我正在尝试从字符串列表中获取 IP 地址的主机。

ips <- c('140.112.204.42', '132.212.14.139', '31.2.47.93', '7.112.221.238')

我想从 ips 中获取前 2 位数字。输出:

ips <- c('140.112', '132.212', '31.2', '7.112')

这是我为转换它们而编写的代码:

cat(unlist(strsplit(ips, "\\.", fixed = FALSE))[1:2], sep = ".")

当我最后检查单个 ips 的类型时,我会得到这样的结果:

140.112 NULL

不知道我做错了什么。如果你有一些与此完全不同的想法,那也很好。

【问题讨论】:

    标签: r string


    【解决方案1】:

    sub:

    ips <- c('140.112.204.42', '132.212.14.139', '31.2.47.93', '7.112.221.238')
    
    sub('\\.\\d+\\.\\d+$', '', ips)
    # [1] "140.112" "132.212" "31.2"    "7.112"
    

    str_extract 来自stringr

    library(stringr)
    str_extract(ips, '^\\d+\\.\\d+')
    # [1] "140.112" "132.212" "31.2"    "7.112"
    

    strsplit + sapply:

    sapply(strsplit(ips, '\\.'), function(x) paste(x[1:2], collapse = '.'))
    # [1] "140.112" "132.212" "31.2"    "7.112"
    

    read.table + apply:

    apply(read.table(textConnection(ips), sep='.')[1:2], 1, paste, collapse = '.')
    #[1] "140.112" "132.212" "31.2"    "7.112"
    

    注意事项:

    1. sub('\\.\\d+\\.\\d+$', '', ips)

      我。 \\.\\d+\\.\\d+$ 匹配文字点、数字一次或多次、文字点再次和数字一次或多次在字符串末尾

      二。 sub 从字符串中删除上述匹配项

    2. str_extract(ips, '^\\d+\\.\\d+'):

      我。 ^\\d+\\.\\d+ 匹配一个数字一次或多次,一个文字点和一个数字一次或多次在字符串的开头

      二。 str_extract 从字符串中提取上述匹配项

    3. sapply(strsplit(ips, '\\.'), function(x) paste(x[1:2], collapse = '.')):

      我。 strsplit(ips, '\\.') 使用文字点作为分隔符拆分每个 ip。这将返回拆分后的向量列表

      二。使用sapplypaste(x[1:2], collapse = '.') 应用于列表的每个元素,因此仅从每个向量中获取前两个数字,并用点作为分隔符将它们折叠起来。 sapply 然后将列表强制转换为向量,从而返回所需 ips 的向量。

    4. apply(read.table(textConnection(ips), sep='.')[1:2], 1, paste, collapse = '.'):

      我。 read.table(textConnection(ips), sep='.')[1:2]ips 视为文本输入,并以点作为分隔符将其读入。只取前两列。

      二。 apply 使paste 可以在每一行上操作,并用一个点折叠。

    【讨论】:

    • 加上read.table你不需要apply你可以使用do.call(paste,c(sep='.',read.table(textConnection(ips), sep='.')[1:2]))
    • 有了更大的数据,我相信 do.call 会超过 apply
    【解决方案2】:

    请您尝试关注一下。

    gsub("([0-9]+.[0-9]+)(.*)","\\1",ips)
    

    解释: 使用gsub 函数并将正则表达式放在那里以匹配数字,然后是 DOT,然后是内存的第一个占位符中的数字,并将 .* 之后的所有内容保留在第二个内存的占位符。然后将这些替换为 \\1 与第一个正则表达式的值,这将是前 2 个字段。

    【讨论】:

      【解决方案3】:

      一种解决方案如下:

      vapply(strsplit(ips, ".", fixed = TRUE), 
             function(x) paste(x[1:2], collapse = "."), 
             character(1L))
      
      • vapplyfunction(x) 应用于 strsplit 的输出的每个元素
      • strsplit 生成一个列表,其中列表的每个元素都是由"." 分隔的 IP 地址的组成部分;设置fixed = TRUE 请求使用拆分字符串的确切值(即".")进行拆分,而不是使用正则表达式
      • function(x) 将来自strsplitpastes 的每个项目的前两个元素(x[1:2])放在一起,由"." 分隔
      • character(1L) 告诉 vapply 输出的每个元素(即从 function(x) 返回的元素应该是长度为 1 的字符串。

      编辑:@user 在我之前发布了这个解决方案(使用 sapply)。

      【讨论】:

        【解决方案4】:

        substr 在 stop 参数上被向量化,因此您可以将其与第二个点之前的位置向量一起使用。 regexpr 给出了第一场比赛的位置,所以如果你 sub 出第一场比赛,你可以在第二场比赛中匹配 - 根据需要,这将是在它的真实位置之前方便的一个(因为你删除了第一个)。

        substr(ips,1,regexpr("\\.",sub("\\.","",ips)))
        [1] "140.112" "132.212" "31.2"    "7.112"
        

        【讨论】:

          【解决方案5】:

          我们可以将 ip 地址转换为 numeric_version 类,然后使用这个不使用正则表达式的基本 R 单线进行格式化:

          format(numeric_version(ips)[, 1:2])
          [1] "140.112" "132.212" "31.2"    "7.112"  
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-08-16
            • 1970-01-01
            • 2011-10-07
            • 1970-01-01
            • 2019-09-26
            • 1970-01-01
            • 1970-01-01
            • 2017-06-04
            相关资源
            最近更新 更多