Oto sposób wyodrębniania wszystkich nakładających się dopasowań o różnej długości przy użyciu gregexpr
.
x<-"abaaaababaaa"
# nest in lookahead + capture group
# to get all instances of the pattern "(ab)|b"
matches<-gregexpr('(?=((ab)|b))', x, perl=TRUE)
# regmatches will reference the match.length attr. to extract the strings
# so move match length data from 'capture.length' to 'match.length' attr
attr(matches[[1]], 'match.length') <- as.vector(attr(matches[[1]], 'capture.length')[,1])
# extract substrings
regmatches(x, matches)
# [[1]]
# [1] "ab" "b" "ab" "b" "ab" "b"
Sztuką jest, aby otoczyć deseń w grupie przechwytywania i tej grupy przechwytywania w twierdzeniu uprzedzona. gregexpr
zwróci listę zawierającą pozycje początkowe z atrybutem capture.length
, macierz, w której pierwsza kolumna odpowiada długościom dopasowania pierwszej grupy przechwytywania. Jeśli przekształcisz to w wektor i przeniesiesz go do atrybutu match.length
(który jest zerowy, ponieważ cały wzorzec był wewnątrz asercji wyprzedzającej), możesz przekazać go do regmatches
, aby wyodrębnić ciągi.
Zgodnie z typem wyniku końcowego, z kilkoma modyfikacjami, może to być wektoryzowane, dla przypadku, gdy x
jest listą ciągów.
x<-list(s1="abaaaababaaa", s2="ab")
matches<-gregexpr('(?=((ab)|b))', x, perl=TRUE)
# make a function that replaces match.length attr with capture.length
set.match.length<-
function(x) structure(x, match.length=as.vector(attr(x, 'capture.length')[,1]))
# set match.length to capture.length for each match object
matches<-lapply(matches, set.match.length)
# extract substrings
mapply(regmatches, x, lapply(matches, list))
# $s1
# [1] "ab" "b" "ab" "b" "ab" "b"
#
# $s2
# [1] "ab" "b"
Wykonuje to również zadanie (do góry), ale chcę uniknąć wyraźnych pętli, moje ciągi są dość długie. –
@AdityaSihag, z pewnością można go było zoptymalizować, po prostu chciałem też wrzucić to rozwiązanie. –