Pobieranie i usuwanie pierwszego znaku ciągu


102

Chciałbym zrobić 2-wymiarowe spacery używając ciągów znaków, przypisując różne wartości do każdego znaku. Planowałem „wystrzelić” pierwszy znak łańcucha, użyć go i powtórzyć dla pozostałej części ciągu.

Jak mogę osiągnąć coś takiego?

x <- 'hello stackoverflow'

Chciałbym móc zrobić coś takiego:

a <- x.pop[1]

print(a)

'h'
print(x)

'ello stackoverflow'

Odpowiedzi:


167

Zobacz ?substring.

x <- 'hello stackoverflow'
substring(x, 1, 1)
## [1] "h"
substring(x, 2)
## [1] "ello stackoverflow"

Pomysł posiadania popmetody, która zarówno zwraca wartość, jak i ma efekt uboczny aktualizacji przechowywanych danych, xjest w dużej mierze koncepcją z programowania obiektowego. Więc zamiast definiować popfunkcję działającą na wektorach znakowych, możemy utworzyć klasę referencyjną za pomocą popmetody.

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"

15

Jest też str_subz pakietu stringr

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

10

Użyj tej funkcji z stringipakietu

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

8

substringjest zdecydowanie najlepsza, ale oto jedna strsplitalternatywa, ponieważ jeszcze jej nie widziałem.

> x <- 'hello stackoverflow'
> strsplit(x, '')[[1]][1]
## [1] "h"

lub równoważnie

> unlist(strsplit(x, ''))[1]
## [1] "h"

pasteResztę struny możesz z powrotem połączyć.

> paste0(strsplit(x, '')[[1]][-1], collapse = '')
## [1] "ello stackoverflow"

5

usuwanie pierwszych znaków:

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

Pomysł polega na zaznaczeniu wszystkich znaków, począwszy od 2 do liczby znaków w x. Jest to ważne, gdy masz nierówną liczbę znaków w słowie lub frazie.

Wybór pierwszej litery jest banalny, podobnie jak poprzednie odpowiedzi:

substring(x,1,1)

2

Inną alternatywą jest użycie przechwytywania wyrażeń podrzędnych z funkcjami wyrażeń regularnych regmatchesi regexec.

# the original example
x <- 'hello stackoverflow'

# grab the substrings
myStrings <- regmatches(x, regexec('(^.)(.*)', x))

Zwraca cały ciąg, pierwszy znak i wynik „popped” w postaci listy o długości 1.

myStrings
[[1]]
[1] "hello stackoverflow" "h"                   "ello stackoverflow" 

co jest równoważne z list(c(x, substr(x, 1, 1), substr(x, 2, nchar(x)))). Oznacza to, że zawiera super zestaw żądanych elementów, a także pełny ciąg.


Dodanie sapplypozwoli tej metodzie działać dla wektora znakowego o długości> 1.

# a slightly more interesting example
xx <- c('hello stackoverflow', 'right back', 'at yah')

# grab the substrings
myStrings <- regmatches(x, regexec('(^.)(.*)', xx))

Zwraca listę z dopasowanym pełnym ciągiem jako pierwszym elementem i pasującymi wyrażeniami podrzędnymi przechwyconymi przez ()następujące elementy. Więc w wyrażeniu regularnym '(^.)(.*)', (^.)pasuje do pierwszego znaku i (.*)dopasowuje pozostałe znaki.

myStrings
[[1]]
[1] "hello stackoverflow" "h"                   "ello stackoverflow" 

[[2]]
[1] "right back" "r"          "ight back" 

[[3]]
[1] "at yah" "a"      "t yah" 

Teraz możemy użyć zaufanej metody sapply+ [do wyciągnięcia żądanych podciągów.

myFirstStrings <- sapply(myStrings, "[", 2)
myFirstStrings
[1] "h" "r" "a"
mySecondStrings <- sapply(myStrings, "[", 3)
mySecondStrings
[1] "ello stackoverflow" "ight back"          "t yah"

To bardzo fajna sztuczka, ale myślę, że pomija to pytanie.
— pedrosaurio

Będziesz musiał wyjaśnić więcej, ponieważ może dać taki sam wynik, jak inne odpowiedzi. Zobacz ostatni blok kodu używany sapplydo wyodrębniania. „Wystrzelenie” pierwszego znaku, jak określono w pytaniu, polega na powtórzeniu tego procesu na powstałym wektorze (mySecondStrings).
— lmo

Jasne, że działa z dodatkowym wyjaśnieniem, które właśnie dodałeś, ale nadal uważam, że jest bardziej zawiłe niż powinno.
— pedrosaurio
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.