R:从字符串集中修剪连续的尾随和前导特殊字符

时间:2015-09-04 15:23:51

标签: r character

我有一个字符向量列表,所有长度相等。示例数据:

> a = list('**aaa', 'bb*bb', 'cccc*')
> a = sapply(a, strsplit, '')
> a
[[1]]
[1] "*" "*" "a" "a" "a"

[[2]]
[1] "b" "b" "*" "b" "b"

[[3]]
[1] "c" "c" "c" "c" "*"

我想确定字符*的所有前导和后续连续出现的索引。然后我想从列表中的所有三个向量中删除这些索引。通过尾随和引导连续字符,我的意思是,例如要么只有一次出现,如第三次出现(cccc*),要么多次连续出现,如第一次出现(**aaa)。

删除后,所有三个字符向量仍应具有相同的长度。

因此,应从所有三个向量中删除前两个和最后一个字符。

[[1]]
[1] "a" "a"

[[2]]
[1] "*" "b"

[[3]]
[1] "c" "c"

请注意,所需结果的第二个向量仍将具有前导*,但它在操作后成为第一个字符,因此它应该在。

我尝试使用which来识别索引(sapply(a, function(x)which(x=='*'))),但这仍然需要一些代码来检测尾随索引。

有关简单解决方案的任何想法吗?

2 个答案:

答案 0 :(得分:2)

我会用NA替换主星和滞后星:

aa <- lapply(setNames(a,seq_along(a)), function(x) {
  star = x=="*"
  toNA = cumsum(!star) == 0 | rev(cumsum(rev(!star))) == 0
  replace(x, toNA, NA)
})

存储在data.frame中:

DF <- do.call(data.frame, c(aa, list(stringsAsFactors=FALSE)) )

使用NA忽略所有行:

res <- na.omit(DF)
#   X1 X2 X3
# 3  a  *  c
# 4  a  b  c

如果你讨厌data.frames并想要你的列表:lapply(res,I)c(unclass(res)),那么

$X1
[1] "a" "a"

$X2
[1] "*" "b"

$X3
[1] "c" "c"

答案 1 :(得分:0)

首先,就像Richard Scriven在评论中提到的那样,你的输出与你要求的东西不一样。您要求删除前导和尾随字符,但您给定的理想输出只是字符列表的第3和第4个元素。 这可以通过像

这样的东西轻松实现
a <- list('**aaa', 'bb*bb', 'cccc*')
alist = sapply(a, strsplit, '')
lapply(alist, function(x) x[3:4])

现在回答问题:

恕我直言,此处不需要sapply()。 你需要grep系列的一个函数直接对你的角色进行操作,这些角色都在R中打开了一个帮助页面?grep。

我会为您的问题提出gsub()和一些正则表达式:

a <- list('**aaa', 'bb*bb', 'cccc*')
b <- gsub(pattern = "^(\\*)*", x = a, replacement = "")
c <- gsub(pattern = "(\\*)*$", x = b, replacement = "")
> c
[1] "aaa"   "bb*bb" "cccc" 

这在一个正则表达式中是可行的,但是你需要对我认为之间的东西进行反向引用,而且我没有让它工作。

如果您熟悉magrittr包及其出色的管道操作员,您可以更优雅地完成此任务:

library(magrittr)
gsub(pattern = "^(\\*)*", x = a, replacement = "") %>%
gsub(pattern = "(\\*)*$", x = ., replacement = "")