我想通过给每个字符分配不同的值,使用字符串进行一些二维行走。我计划“弹出”字符串的第一个字符,使用它,并重复执行剩余部分的操作。
如何实现这样的操作?
x <- 'hello stackoverflow'
我想要能够像这样做:
a <- x.pop[1]
print(a)
'h'
print(x)
'ello stackoverflow'
?substring
。x <- 'hello stackoverflow'
substring(x, 1, 1)
## [1] "h"
substring(x, 2)
## [1] "ello stackoverflow"
拥有一个既返回值又具有更新存储在x
中的数据副作用的pop
方法,这个想法非常符合面向对象编程的概念。因此,我们可以创建一个引用类并定义一个pop
方法来操作字符向量。
PopStringFactory <- setRefClass(
"PopString",
fields = list(
x = "character"
),
methods = list(
initialize = function(x)
{
x <<- x
},
pop = function(n = 1)
{
if(nchar(x) == 0)
{
warning("Nothing to pop.")
return("")
}
first <- substring(x, 1, n)
x <<- substring(x, n + 1)
first
}
)
)
x <- PopStringFactory$new("hello stackoverflow")
x
## Reference class object of class "PopString"
## Field "x":
## [1] "hello stackoverflow"
replicate(nchar(x$x), x$pop())
## [1] "h" "e" "l" "l" "o" " " "s" "t" "a" "c" "k" "o" "v" "e" "r" "f" "l" "o" "w"
还有来自stringr包的str_sub
x <- 'hello stackoverflow'
str_sub(x, 2) # or
str_sub(x, 2, str_length(x))
[1] "ello stackoverflow"
substring
明显是最好的选择,但以下是一个 strsplit
的替代方案,因为我还没有看到过这样的方案。
> x <- 'hello stackoverflow'
> strsplit(x, '')[[1]][1]
## [1] "h"
或等价地
> unlist(strsplit(x, ''))[1]
## [1] "h"
你可以将剩下的字符串 粘贴
回来。
> paste0(strsplit(x, '')[[1]][-1], collapse = '')
## [1] "ello stackoverflow"
使用来自stringi
包的此函数
> x <- 'hello stackoverflow'
> stri_sub(x,2)
[1] "ello stackoverflow"
删除前几个字符:
x <- 'hello stackoverflow'
substring(x, 2, nchar(x))
Idea是选择从2开始到x中的字符数。当单词或短语中的字符数不相等时,这一点非常重要。
选择第一个字母与之前的答案一样简单:
substring(x,1,1)
另一种选择是使用正则表达式函数regmatches
和regexec
中的捕获子表达式。
# the original example
x <- 'hello stackoverflow'
# grab the substrings
myStrings <- regmatches(x, regexec('(^.)(.*)', x))
这将返回一个长度为1的列表,其中包含整个字符串、第一个字符以及“弹出”的结果。
myStrings
[[1]]
[1] "hello stackoverflow" "h" "ello stackoverflow"
这相当于 list(c(x, substr(x, 1, 1), substr(x, 2, nchar(x))))
。也就是说,它包含所需元素的超集以及完整字符串。
添加sapply
将使此方法适用于长度 > 1 的字符向量。
# a slightly more interesting example
xx <- c('hello stackoverflow', 'right back', 'at yah')
# grab the substrings
myStrings <- regmatches(x, regexec('(^.)(.*)', xx))
这返回一个列表,其中匹配的完整字符串作为第一个元素,由()
捕获的匹配子表达式作为后续元素。因此,在正则表达式'(^.)(.*)'
中,(^.)
匹配第一个字符,(.*)
匹配剩余字符。
myStrings
[[1]]
[1] "hello stackoverflow" "h" "ello stackoverflow"
[[2]]
[1] "right back" "r" "ight back"
[[3]]
[1] "at yah" "a" "t yah"
现在,我们可以使用可靠的sapply
+[
方法来提取所需的子字符串。
myFirstStrings <- sapply(myStrings, "[", 2)
myFirstStrings
[1] "h" "r" "a"
mySecondStrings <- sapply(myStrings, "[", 3)
mySecondStrings
[1] "ello stackoverflow" "ight back" "t yah"
使用 sub 函数的另一种方法。
sub('(^.).*', '\\1', 'hello stackoverflow')
[1] "h"
sub('(^.)(.*)', '\\2', 'hello stackoverflow')
[1] "ello stackoverflow"
sapply
进行提取的最终代码块。如问题中所指定的“弹出”第一个字符,是在结果向量(mySecondStrings)上重复此过程的问题。 - lmo