2013-04-24 17 views
10

Ho due variabili di carattere (nomi di oggetti) e voglio estrarre la più grande sottostringa comune.Trova sottostringhe comuni tra due variabili di carattere

a <- c('blahABCfoo', 'blahDEFfoo') 
b <- c('XXABC-123', 'XXDEF-123') 

voglio il seguente come risultato:

[1] "ABC" "DEF" 

Questi vettori come input dovrebbero dare lo stesso risultato:

a <- c('textABCxx', 'textDEFxx') 
b <- c('zzABCblah', 'zzDEFblah') 

Questi esempi sono rappresentativi. Le stringhe contengono elementi identificativi e il resto del testo in ogni elemento del vettore è comune, ma sconosciuto.

C'è una soluzione, in uno dei seguenti posti (in ordine di preferenza):

  1. Base R

  2. pacchetti raccomandati

  3. pacchetti disponibili sul CRAN

La risposta al presunto duplicato fa n ot soddisfare questi requisiti.

+0

Controlla questa domanda: http://stackoverflow.com/questions/ 1429476/longest-common-substring-problem – dave

+1

Anche questo: http://finzi.psych.upenn.edu/R/Rhelp02a/archive/68013.html –

+0

http://svitsrv25.epfl.ch/R-doc/library /Biostrings/html/pmatchPattern.html e questo http://www.emoticode.net/r/longest-common-substring.html –

risposta

8

Ecco un pacchetto CRAN per questo:

library(qualV) 

sapply(seq_along(a), function(i) 
    paste(LCS(strsplit(a[i], '')[[1]], strsplit(b[i], '')[[1]])$LCS, 
      collapse = "")) 
+1

(+1) per pacchetto CRAN. Trovo l'input per questa funzione * davvero * strana però. Voglio dire, è ovvio che uno deve creare tutti i suffissi. Perché chiedere all'utente di farlo? La cosa bella è che hanno la loro implementazione di LCS in C. – Arun

+0

che ha a che fare con il resto del pacchetto - la maggior parte dell'elaborazione viene eseguita sui vettori – eddi

+0

Non mi interessa la funzione prendere gli input vettoriali. Ma dovrebbe essere solo "LCS (a [i], b [i])" è ciò che intendevo. Non dovremmo generare suffissi. – Arun

9

Se non vi dispiace usare i pacchetti di bioconduttori, quindi, è possibile utilizzare Rlibstree. L'installazione è piuttosto semplice.

source("http://bioconductor.org/biocLite.R") 
biocLite("Rlibstree") 

Poi, si può fare:

require(Rlibstree) 
ll <- list(a,b) 
lapply(data.frame(do.call(rbind, ll), stringsAsFactors=FALSE), 
      function(x) getLongestCommonSubstring(x)) 

# $X1 
# [1] "ABC" 

# $X2 
# [1] "DEF" 

Su un lato nota: io non sono molto sicuro se Rlibstree utilizza libstree 0.42 o libstree 0.43. Entrambe le librerie sono presenti nel pacchetto sorgente. Ricordo di aver incontrato una perdita di memoria (e quindi un errore) su un enorme array in perl che utilizzava libstree 0.42. Solo un avviso.

0

Perché ho troppe cose che non vogliono fare, ho fatto questo, invece:

Rgames> for(jj in 1:100) { 
+ str2<-sample(letters,100,rep=TRUE) 
+ str1<-sample(letters,100,rep=TRUE) 
+ longs[jj]<-length(lcstring(str1,str2)[[1]]) 
+ } 
Rgames> table(longs) 
longs 
2 3 4 
59 39 2 

Chiunque cura di fare una statistica stima della distribuzione effettiva delle stringhe corrispondenti? (lcstring (lcstring) è una funzione a rotazione bruta, l'output contiene tutte le stringhe massime, motivo per cui guardo solo il primo elemento dell'elenco)

Problemi correlati