การรับและลบอักขระตัวแรกของสตริง


106

ฉันต้องการเดินแบบ 2 มิติโดยใช้สตริงของอักขระโดยกำหนดค่าที่แตกต่างกันให้กับตัวละครแต่ละตัว ฉันวางแผนที่จะ 'ป๊อป' อักขระตัวแรกของสตริงใช้มันและทำซ้ำสำหรับส่วนที่เหลือของสตริง

ฉันจะบรรลุสิ่งนี้ได้อย่างไร?

x <- 'hello stackoverflow'

ฉันต้องการที่จะทำสิ่งนี้:

a <- x.pop[1]

print(a)

'h'
print(x)

'ello stackoverflow'

คำตอบ:


176

ดู?substring.

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

แนวคิดของการมีpopวิธีการที่ทั้งส่งคืนค่าและมีผลข้างเคียงจากการอัปเดตข้อมูลที่จัดเก็บไว้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"

15

นอกจากนี้ยังมีstr_subจากแพ็คเกจ stringr

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


8

substringดีที่สุดแน่นอน แต่นี่เป็นstrsplitทางเลือกหนึ่งเนื่องจากฉันยังไม่เห็น

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

หรือเทียบเท่า

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

และคุณสามารถpasteนำสตริงที่เหลือกลับมารวมกันได้

> paste0(strsplit(x, '')[[1]][-1], collapse = '')
## [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))

สิ่งนี้จะส่งคืนสตริงทั้งหมดอักขระตัวแรกและผลลัพธ์ "popped" ในรายการความยาว 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" 

ตอนนี้เราสามารถใช้วิธี trusty sapply+ [เพื่อดึงสตริงย่อยที่ต้องการออกมา

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

นี่เป็นเคล็ดลับที่ดีมาก แต่ฉันคิดว่าไม่มีคำถาม
pedrosaurio

คุณจะต้องอธิบายเพิ่มเติมเนื่องจากสามารถให้ผลลัพธ์เดียวกันกับคำตอบอื่น ๆ ดูบล็อกสุดท้ายของรหัสที่ใช้sapplyสำหรับการแยก "popping" อักขระตัวแรกตามที่ระบุไว้ในคำถามเป็นเรื่องของการทำซ้ำขั้นตอนนี้กับเวกเตอร์ผลลัพธ์ (mySecondStrings)
lmo

แน่นอนว่ามันใช้งานได้กับคำอธิบายเพิ่มเติมที่คุณเพิ่งเพิ่ม แต่ฉันยังพบว่ามันซับซ้อนกว่าที่ควร
pedrosaurio
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.