2017-03-15 68 views
8

有沒有辦法將按字母順序排列的字符串部分分開?在較大的字符串中分離字母字符串

換句話說,如果你有一個這樣的字符串:hjubcdepyvb

你能不能拔出部分按字母順序排列?:bcde

我曾想過使用is.unsorted()功能,但我我不知道如何將它應用於字符串的一部分。

回答

8

這裏是通過轉換爲ASCII和背部的一種方式:

input <- "hjubcdepyvb" 
spl_asc <- as.integer(charToRaw(input))  # Convert to ASCII 
d1 <- diff(spl_asc) == 1      # Find sequences 
filt <- spl_asc[c(FALSE, d1) | c(d1, FALSE)] # Only keep sequences (incl start and end) 
rawToChar(as.raw(filt))      # Convert back to character 

#[1] "bcde" 

注意,這將串聯是按字母順序排列的任何部分。

即如果輸入是"abcxasdicfgaqwe"則輸出將是abcfg

如果你想獲得不同的載體對於每個順序串,你可以做以下

input <- "abcxasdicfgaqwe" 
spl_asc <- as.integer(charToRaw(input)) 
d1 <- diff(spl_asc) == 1 
r <- rle(c(FALSE, d1) | c(d1, FALSE))     # Find boundaries 
cm <- cumsum(c(1, r$lengths))       # Map these to string positions 
substring(input, cm[-length(cm)], cm[-1] - 1)[r$values] # Extract matching strings 

最後,我只好想出一個辦法使用正則表達式:

input <- c("abcxasdicfgaqwe", "xufasiuxaboqdasdij", "abcikmcapnoploDEFgnm", 
      "acfhgik") 
(rg <- paste0("(", paste0(c(letters[-26], LETTERS[-26]), 
          "(?=", c(letters[-1], LETTERS[-1]), ")", collapse = "|"), ")+.")) 

#[1] "(a(?=b)|b(?=c)|c(?=d)|d(?=e)|e(?=f)|f(?=g)|g(?=h)|h(?=i)|i(?=j)|j(?=k)| 
#k(?=l)|l(?=m)|m(?=n)|n(?=o)|o(?=p)|p(?=q)|q(?=r)|r(?=s)|s(?=t)|t(?=u)|u(?=v)| 
#v(?=w)|w(?=x)|x(?=y)|y(?=z)|A(?=B)|B(?=C)|C(?=D)|D(?=E)|E(?=F)|F(?=G)|G(?=H)| 
#H(?=I)|I(?=J)|J(?=K)|K(?=L)|L(?=M)|M(?=N)|N(?=O)|O(?=P)|P(?=Q)|Q(?=R)|R(?=S)| 
#S(?=T)|T(?=U)|U(?=V)|V(?=W)|W(?=X)|X(?=Y)|Y(?=Z))+." 

regmatches(input, gregexpr(rg, input, perl = TRUE)) 
#[[1]] 
#[1] "abc" "fg" 
# 
#[[2]] 
#[1] "ab" "ij" 
# 
#[[3]] 
#[1] "abc" "nop" "DEF" 
# 
#[[4]] 
#character(0) 

這正則表達式將識別連續的大寫或小寫字母(但不是混合大小寫)。正如所證明的,它適用於字符向量,並生成一個所有匹配的向量列表。如果找不到匹配項,則輸出爲character(0)

3
myf = function(x){ 
    x = unlist(strsplit(x, "")) 
    ind = charmatch(x, letters) 
    d = c(0, diff(ind)) 
    d[d !=1] = 0 
    d = d + c(sapply(1:(length(d)-1), function(i) { 
     ifelse(d[i] == 0 & d[i+1] == 1, 1, 0) 
    } 
    ), 0) 
    d = split(seq_along(d)[d!=0], with(rle(d), rep(seq_along(values), lengths))[d!=0]) 
    return(sapply(d, function(a) paste(x[a], collapse = ""))) 
} 

myf(x = "hjubcdepyvblltpqrs") 
#  2  4 
#"bcde" "pqrs" 
4

使用因子整數轉換:

input <- "hjubcdepyvb" 
d1 <- diff(as.integer(factor(unlist(strsplit(input, "")), levels = letters))) == 1 
filt <- c(FALSE, d1) | c(d1, FALSE) 
paste(unlist(strsplit(input, ""))[filt], collapse = "") 
# [1] "bcde"