2016-03-23 17 views
8

Tôi có hai chuỗi, a <- "AERRRTX"; b <- "TRRA".Trích xuất các ký tự riêng biệt khác nhau giữa hai chuỗi

tôi muốn trích xuất các ký tự trong a không được sử dụng trong b, tức là "ERX"

Tôi đã thử các câu trả lời trong Extract characters that differ between two strings, trong đó sử dụng setdiff. Nó trả về "EX", bởi vì b không có "R" và setdiff sẽ loại bỏ tất cả ba "R" trong a. Mục tiêu của tôi là để đối xử với mỗi nhân vật là khác biệt, vì vậy chỉ có hai trong số ba R trong a nên được loại bỏ.

Bất kỳ đề xuất nào về những gì tôi có thể sử dụng thay vì setdiff hoặc một số cách tiếp cận khác để đạt được kết quả đầu ra của tôi?

Trả lời

10

Một cách tiếp cận khác nhau sử dụng pmatch,

a1 <- unlist(strsplit(a, "")) 
b1 <- unlist(strsplit(b, "")) 

a1[!1:length(a1) %in% pmatch(b1, a1)] 

#[1] "E" "R" "X" 

Một ví dụ khác,

a <- "Ronak";b<-"Shah" 

a1 <- unlist(strsplit(a, "")) 
b1 <- unlist(strsplit(b, "")) 
a1[!1:length(a1) %in% pmatch(b1, a1)] 

# [1] "R" "o" "n" "k" 
+1

điểm nhỏ: Đó là khuyến khích để tránh gán 'c', vì nó là hàm dựng sẵn thường được sử dụng. Nếu 'c' là một biến được định nghĩa trong bất kỳ môi trường kèm theo nào, các tham chiếu đến từ định danh đó có thể liên kết với nó, điều này có thể làm hỏng rất nhiều mã. Ví dụ, 'do.call (c, ...)' không thành công trong trường hợp này. – bgoldst

+0

@bgoldst bạn nói đúng. Đã cập nhật. Cảm ơn! –

+2

Thay thế tốt. Bạn có thể thay thế dòng thứ ba bằng 'a1 [-pmatch (b1, a1)]'. Ngoài ra, sẽ hữu ích khi lưu ý đối số "duplicateates.ok = FALSE" của 'pmatch' để phân biệt hành vi của nó với' match' –

4

Chúng ta có thể sử dụng Reduce() để tiếp loại bỏ từ a mỗi nhân vật được tìm thấy trong b:

a <- 'AERRRTX'; b <- 'TRRA'; 
paste(collapse='',Reduce(function(as,bc) as[-match(bc,as,nomatch=length(as)+1L)],strsplit(b,'')[[1L]],strsplit(a,'')[[1L]])); 
## [1] "ERX" 

này sẽ giữ gìn trật tự của các nhân vật sống sót trong a.


Một cách khác là để đánh dấu từng nhân vật với chỉ số lần xuất hiện của nó trong a, làm tương tự cho b, và sau đó chúng ta có thể sử dụng setdiff():

a <- 'AERRRTX'; b <- 'TRRA'; 
pasteOccurrence <- function(x) ave(x,x,FUN=function(x) paste0(x,seq_along(x))); 
paste(collapse='',substr(setdiff(pasteOccurrence(strsplit(a,'')[[1L]]),pasteOccurrence(strsplit(b,'')[[1L]])),1L,1L)); 
## [1] "ERX" 
4

Bạn có thể sử dụng chức năng vsetdiff từ vecsets gói

install.packages("vecsets") 
library(vecsets) 
a <- "AERRRTX" 
b <- "TRRA" 
Reduce(vsetdiff, strsplit(c(a, b), split = "")) 
## [1] "E" "R" "X" 
3

Một thay thế sử dụng data.table package`:

library(data.table) 

x = data.table(table(strsplit(a, '')[[1]])) 
y = data.table(table(strsplit(b, '')[[1]])) 

dt = y[x, on='V1'][,N:=ifelse(is.na(N),0,N)][N!=i.N,res:=i.N-N][res>0] 

rep(dt$V1, dt$res) 
#[1] "E" "R" "X" 
+0

Rất tốt, + 1.᠎ – bgoldst

Các vấn đề liên quan