2016-03-23 15 views
8

Ho due stringhe, a <- "AERRRTX"; b <- "TRRA".Estrarre caratteri distinti che differiscono tra due stringhe

Voglio estrarre i personaggi di a non utilizzate in b, vale a dire "ERX"

ho cercato la risposta in Extract characters that differ between two strings, che utilizza setdiff. Restituisce "EX", perché b ha "R" e setdiff eliminerà tutte e tre le "R" in a. Il mio obiettivo è quello di trattare ogni personaggio come distinto, quindi solo due delle tre R in a dovrebbero essere eliminate.

Qualche suggerimento su cosa posso utilizzare al posto di setdiff o qualche altro approccio per raggiungere il mio risultato?

risposta

10

Un approccio diverso utilizzando pmatch,

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

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

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

Un altro esempio,

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

Punto minore: E 'consigliabile per evitare di assegnare 'c', poiché è una funzione incorporata comunemente usata. Se 'c' è una variabile definita in qualsiasi ambiente che racchiude, i riferimenti a tale identificatore possono associarsi ad esso, il che può rovinare un sacco di codice. Ad esempio, 'do.call (c, ...)' fallisce in questo caso. – bgoldst

+0

@bgoldst hai ragione. Aggiornato. Grazie! –

+2

Bella alternativa. È possibile sostituire la terza riga con 'a1 [-pmatch (b1, a1)]'. Inoltre, sarebbe utile notare l'argomento "duplicates.ok = FALSE" di 'pmatch' che differenzia il suo comportamento in' match' –

4

Possiamo usare Reduce() per eliminare in successione da a ogni carattere si trovano in 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" 

Ciò manterrà l'ordine dei personaggi sopravvissuti a a.


Un altro approccio è quello di contrassegnare ogni personaggio con il suo indice di ricorrenza nel a, fare lo stesso per b, e quindi possiamo usare 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

È possibile utilizzare la funzione vsetdiff da vecsets pacchetto

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

Un'alternativa utilizzando 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

Molto buono, + 1.᠎ – bgoldst

Problemi correlati