将一个字符串分割成单个字符

3

我有一些被编码成字符串的有序测试结果。该字符串长度可以任意。字符串中的每个数字代表一个测试结果,例如下面这个例子中表示了四个测试结果:

2069

我想在R中通过将该字符串分割为单个观测值来整理这些数据。使用strsplitstring::str_split没有问题,它们会返回四个值,这些值将成为我的观测值。

strsplit("2069" %>% as.character(), split = "") %>% unlist()
[1] "2" "0" "6" "9"

然而,我现在意识到有一些结果是大于9的值。这些两位数的值已经用括号编码,以明确它们不是单独的结果。

例如,在以下情况下,我仍然有四个值,但是有些值已经用括号括起来,以分组大于9的值。

2(10)1(12)

我正在努力找到一种方法来分解这些数字,使得我得到

[1] "2" "10" "1" "12"

感谢任何指导。谢谢。

3个回答

3

更新 - 根据评论中作者提供的新样式进行基于模式匹配。 这里,我们使用str_extract函数提取位于括号之后一个或多个数字(正则表达式lookaround),或者任何不是括号的字符([^()])。

library(stringr)
str_extract_all(str1, "(?<=[(])\\d+|[^()]")
[[1]]
[1] "2"  "10" "1"  "12"

[[2]]
[1] "2" "0" "6" "9"

[[3]]
[1] "2"  "15"

[[4]]
[1] "2" "1" "3" "1"

-在OP的额外模式上进行测试

str_extract_all(str2, "(?<=[(])\\d+|[^()]")
[[1]]
[1] "2"  "10" "1"  "12"

[[2]]
[1] "2" "0" "6" "9"

[[3]]
[1] "2"  "15"

[[4]]
[1] "2" "1" "3" "1"

[[5]]
[1] "10" "0"  "2"  "0"  "1" 

-早期解决方案(基于所有大于9的数字都将被包裹在括号内的假设)

我们可以在基础R语言中根据括号进行分割。

unlist(strsplit(str1[1], "\\(|\\)"))
[1] "2"  "10" "1"  "12"

假设存在这两种情况,那么一种选择是获取括号所在元素的索引并分别处理。
i1 <- grepl("\\(|\\)", str1)
lst1 <- vector('list', length(str1))
lst1[i1] <- strsplit(str1[i1], "\\(|\\)")
lst1[!i1] <- strsplit(str1[!i1], "")
unlist(lst1)
[1] "2"  "10" "1"  "12" "2"  "0"  "6"  "9"  "2"  "15" "2"  "1"  "3"  "1" 

另一个选择是使用带有grepl的ifelse来创建单个分隔符,然后使用strsplit。
lst1 <- strsplit(trimws(ifelse(grepl("\\(|\\)", str1), 
    gsub("\\(|\\)", ",", str1), gsub("(?<=.)(?=.)", "\\1,\\2", 
       str1, perl = TRUE)), whitespace = ","), ",")
lst1
[[1]]
[1] "2"  "10" "1"  "12"

[[2]]
[1] "2" "0" "6" "9"

[[3]]
[1] "2"  "15"

[[4]]
[1] "2" "1" "3" "1"

数据

str1 <- c("2(10)1(12)", "2069", "2(15)", "2131")
str2 <- c(str1, "(10)0201")

感谢您的回复,@akrun。我没有清楚地表达我的问题,现在已经进行了编辑以便更加明确。问题是每个编码值代表一个测试结果,除非该值大于9,在这种情况下,测试结果将被括在括号中。 - rdelrossi
@RDelRossi 我更新了帖子以检查那些具有 () 的情况。你能否请检查我的解决方案的第二部分? - akrun
1
最后一个选项非常紧凑和令人印象深刻,太棒了! - ThomasIsCoding
1
实际上,@akrun,那个最近的超紧凑版本现在也解决了我的异常情况问题。 - rdelrossi
1
@akrun:太棒了,谢谢你的帮助,Arun。非常感激。 - rdelrossi
显示剩余3条评论

1
也许我们可以像下面这样做(从@akrun借用str1
> mapply(strsplit, str1, ifelse(grepl("[()]", str1), "\\(|\\)", ""))
$`2(10)1(12)`
[1] "2"  "10" "1"  "12"

$`2069`
[1] "2" "0" "6" "9"

$`2(15)`
[1] "2"  "15"

$`2131`
[1] "2" "1" "3" "1"

0

使用

(?<=\()\d+(?=\))|\d

请查看正则表达式证明

说明

--------------------------------------------------------------------------------
  (?<=                     look behind to see if there is:
--------------------------------------------------------------------------------
    \(                       '('
--------------------------------------------------------------------------------
  )                        end of look-behind
--------------------------------------------------------------------------------
  \d+                      digits (0-9) (1 or more times (matching
                           the most amount possible))
--------------------------------------------------------------------------------
  (?=                      look ahead to see if there is:
--------------------------------------------------------------------------------
    \)                       ')'
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
 |                        OR
--------------------------------------------------------------------------------
  \d                       digits (0-9)

R 代码:

library(stringr)
str1 <- c("2(10)1(12)", "2069", "2(15)", "2131")
str_extract_all(str1, "(?<=\\()\\d+(?=\\))|\\d")

结果:

[1] "2"  "10" "1"  "12"

[[2]]
[1] "2" "0" "6" "9"

[[3]]
[1] "2"  "15"

[[4]]
[1] "2" "1" "3" "1"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接