2013-12-08 3 views
3

는 벡터를 가정 :파이썬의 rsplit()처럼 문자열을 오른쪽에서 왼쪽으로 나누는 방법?

xx.1 <- c("zz_ZZ_uu_d", "II_OO_d") 

나는 새로운 벡터를 잘 대부분에서 갈라 번만 분할 싶어. 예상되는 결과는 다음과 같습니다 그것은 파이썬의 rsplit() 기능 같은 것

c("zz_ZZ_uu", "d", "II_OO", "d"). 

. 현재 나의 생각은 문자열을 뒤집어서 str_split()stringr에 나눈 것입니다.

더 나은 솔루션이 있습니까?

답변

6

부정적 예측 : a(?!b) 말한다

unlist(strsplit(xx.1, "_(?!.*_)", perl = TRUE)) 
# [1] "zz_ZZ_uu" "d"  "II_OO" "d"  

찾을 그런 다음되지 않은 ab. 이 경우 .*_은 더 이상 (.*)이 더 이상 존재해서는 안되는 것을 의미합니다. _ 님.

그러나이 아이디어를 일반화하는 것이 쉽지 않은 것 같습니다. 먼저 _(?=[^_]*$)으로 긍정적 인 미리보기로 다시 쓸 수 있습니다 (_ 뒤에 _이 오는 것을 찾으십시오. 여기에 $은 문자열의 끝을 나타냄). 그렇다면 매우 우아하지 않은 일반화가 될 것입니다.

rsplit <- function(x, s, n) { 
    p <- paste0("[^", s, "]*") 
    rx <- paste0(s, "(?=", paste(rep(paste0(p, s), n - 1), collapse = ""), p, "$)") 
    unlist(strsplit(x, rx, perl = TRUE)) 
} 

rsplit(vec, "_", 1) 
# [1] "a_b_c_d_e_f" "g"   "a"   "b"   
rsplit(vec, "_", 3) 
# [1] "a_b_c_d" "e_f_g" "a_b"  

이 경우 n=3이 함수는 _(?=[^_]*_[^_]*_[^_]*$)을 사용합니다.

+0

+1 정규식 마술. –

+1

나는 perl에 익숙하지 않다. 조금 설명 할 수 있겠는가? 두 개 이상의 "_"을 분할하고 싶다면 어떻게 바꾸어야 하는가? – shao

+1

@ chunxuan, 업데이트를 참조하십시오. – Julius

1

분할 후 붙여 넣기하면 어떨까요?

rsplit <- function(x, s) { 
    spl <- strsplit("zz_ZZ_uu_d", s, fixed=TRUE)[[1]] 
    res <- paste(spl[-length(spl)], collapse=s, sep="") 
    c(res, spl[length(spl)] ) 
} 
> rsplit("zz_ZZ_uu_d", "_") 
[1] "zz_ZZ_uu" "d" 
1

은 또한 아리의 그것과 매우 유사한 접근 방식에 대해 생각

> res <- lapply(strsplit(xx.1, "_"), function(x){ 
    c(paste0(x[-length(x)], collapse="_"), x[length(x)]) 
    }) 

> unlist(res) 
[1] "zz_ZZ_uu" "d"  "II_OO" "d" 
2

또 다른 두. 두 경우 모두 문자열의 두 부분을 캡처하는 패턴으로 "(.*)_(.*)"을 사용합니다. *은 욕심이 많으므로 처음에는 (.*)이 최대한 많은 문자와 일치합니다.

unlist(lapply(regmatches(xx.1, regexec("(.*)_(.*)", xx.1)), 
       tail, -1)) 

을 그리고이 사람은 이해하기 좀 덜 학술하지만 쉽게 :

나는 당신의 susbtrings 시작과 끝 위치를 캡처 할 수 regexec를 사용하여 여기에

regmatches을 재구성하는

unlist(strsplit(sub("(.*)_(.*)", "\\[email protected]@@\\2", xx.1), "@@@")) 
0

이렇게하면 원하는 것을 정확하게 얻을 수 있으며 가장 간단한 방법입니다.

require(stringr) 
as.vector(t(str_match(xx.1, '(.*)_(.*)') [,-1])) 
[1] "zz_ZZ_uu" "d"  "II_OO" "d" 

설명 : 그것은 단지 분할에 왼쪽에서 오른쪽 않으며, 분할 후 모든 (N-1) 왼쪽 일치를 repasting의 총 폐기물이기 때문에

  • str_split(), 당신이 찾고있는 드로이드 아니다 시각. 따라서 str_split()을 두 개의 캡처 그룹이있는 정규식과 함께 사용하십시오.첫 번째 은 마지막으로 _에 해당하는 모든 것에 대해 욕심이 있습니다. 이는 원하는 것입니다. 적어도 하나의 _이없고 NA를 반환하면 실패합니다.
  • str_match()은 첫 번째 열이 전체 문자열이고 이후의 열이 개별 캡처 그룹 인 행렬을 반환합니다. 우리는 첫 번째 열을 원하는, 그래서 당신이 원하는하지 않은, 열이 많다는 그 행렬을 풀다 것이다 [,-1]
  • as.vector()로 드롭, 그래서 우리는 행 방향
  • str_match(string, pattern)가 풀다 조옮김 할 t()를 사용하지 않는 문자열과 패턴 모두에 걸쳐 깔끔한 벡터화.
+0

그건 그렇고, 많은 일을한다면 커스텀 함수'str_rsplit (...) <- function (...) {...}'을 정의하십시오. – smci