获取和删除一个字符串的第一个字符

125

我想通过给每个字符分配不同的值,使用字符串进行一些二维行走。我计划“弹出”字符串的第一个字符,使用它,并重复执行剩余部分的操作。

如何实现这样的操作?

x <- 'hello stackoverflow'

我想要能够像这样做:

a <- x.pop[1]

print(a)

'h'
print(x)

'ello stackoverflow'
7个回答

201
请查看?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"

21

还有来自stringr包的str_sub

x <- 'hello stackoverflow'
str_sub(x, 2) # or
str_sub(x, 2, str_length(x))
[1] "ello stackoverflow"

11

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"

11

使用来自stringi包的此函数

> x <- 'hello stackoverflow'
> stri_sub(x,2)
[1] "ello stackoverflow"

5

删除前几个字符:

x <- 'hello stackoverflow'
substring(x, 2, nchar(x))

Idea是选择从2开始到x中的字符数。当单词或短语中的字符数不相等时,这一点非常重要。

选择第一个字母与之前的答案一样简单:

substring(x,1,1)

2

另一种选择是使用正则表达式函数regmatchesregexec中的捕获子表达式。

# 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"

这是一个非常棒的技巧,但我认为它没有回答问题。 - pedrosaurio
你需要进一步解释,因为它可能会产生与其他答案相同的输出。请参见使用sapply进行提取的最终代码块。如问题中所指定的“弹出”第一个字符,是在结果向量(mySecondStrings)上重复此过程的问题。 - lmo
确实,它能够在你刚添加的额外解释下工作,但我仍然觉得它比应该更复杂。 - pedrosaurio

1

使用 sub 函数的另一种方法。

 sub('(^.).*', '\\1', 'hello stackoverflow')
 [1] "h"

 sub('(^.)(.*)', '\\2', 'hello stackoverflow')
 [1] "ello stackoverflow"

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