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.