2016-03-23 181 views
8

我有兩個字符串,a <- "AERRRTX"; b <- "TRRA"提取兩個字符串之間不同的字符

我想提取a的字符b沒有使用,即「ERX」

我試着在Extract characters that differ between two strings答案,它採用setdiff。它返回「EX」,因爲b的確有「R」,並且setdiff將消除a中的所有三個「R」。我的目標是將每個角色作爲不同的角色來處理,因此只有a中的三個R中的兩個應該被刪除。

我可以用什麼建議而不是setdiff或其他一些方法來實現我的輸出?

回答

10

一種不同的方法使用pmatch

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

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

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

又如,

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

小點:這是明智的避免分配'c',因爲它是一個常用的內置函數。如果'c'是在任何封閉環境中定義的變量,則對該標識符的引用可以綁定到它,這可能會弄亂很多代碼。例如,在這種情況下'do.call(c,...)'失敗。 – bgoldst

+0

@bgoldst你是對的。更新。謝謝! –

+2

不錯的選擇。你可以用'a1 [-pmatch(b1,a1)]'替換你的第三行。另外,注意「pmatch」的「duplicates.ok = FALSE」參數會很有用,它將它的行爲區分爲「匹配」 –

4

我們可以使用Reduce()來先後從a每一個字符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" 

這樣會保留在a倖存的字符的順序。


另一種方法是,以紀念其出現指數的每個字符在a,爲b做同樣的,然後我們就可以使用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

您可以使用該功能vsetdiffvecsets

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

使用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

非常好,+1.᠎ – bgoldst

相關問題