2016-03-23 11 views
8

Mam dwa ciągi znaków, a <- "AERRRTX"; b <- "TRRA".Wyodrębnij różne znaki, które różnią się między dwoma ciągami znaków

chcę wyodrębnić znaki a nieużywane w b, to znaczy „ERX”

Próbowałem odpowiedź w Extract characters that differ between two strings, która wykorzystuje setdiff. Zwraca "EX", ponieważ b ma "R", a setdiff wyeliminuje wszystkie trzy "R" w a. Moim celem jest traktowanie każdej postaci jako odrębnej, tak aby wyeliminować tylko dwa z trzech R w a.

Wszelkie sugestie dotyczące tego, co mogę użyć zamiast setdiff, lub inne podejście do osiągnięcia moich wyników?

Odpowiedz

10

Inne podejście korzystając pmatch,

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

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

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

Innym przykładem,

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

drobna uwaga: Jest to wskazane aby nie przypisywać 'c', ponieważ jest to najczęściej używana wbudowana funkcja. Jeśli 'c' jest zmienną zdefiniowaną w jakimkolwiek otaczającym środowisku, odniesienia do tego identyfikatora mogą się z nim wiązać, co może zepsuć wiele kodu. Na przykład 'do.call (c, ...)' nie powiedzie się w tym przypadku. – bgoldst

+0

@bgoldst masz rację. Zaktualizowano. Dzięki! –

+2

Ładna alternatywa. Możesz zamienić trzecią linię na 'a1 [-pmatch (b1, a1)]'. Warto również zauważyć argument "duplicates.ok = FALSE" z 'pmatch', który różnicuje jego zachowanie na' match' –

4

Możemy użyć Reduce() sukcesywnie eliminować z a każdego znaku znalezionego w 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" 

To będzie zachować kolejność znaków, które przeżyły w a.


Innym podejściem jest oznaczyć każdy znak z jego indeksu występowania w a, zrobić to samo dla b, a następnie możemy użyć 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

Można użyć funkcji vsetdiff od vecsets pakietów

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

Alternatywą korzystania 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

Bardzo dobry, + 1.᠎ – bgoldst

Powiązane problemy