2011-08-04 23 views
17

Tôi muốn xem, nếu "001" hoặc "100" hoặc "000" xảy ra trong một chuỗi gồm 4 ký tự của 01. Ví dụ: chuỗi gồm 4 ký tự có thể giống như "1100" hoặc "0010" hoặc "1001" hoặc "1111". Làm cách nào để kết hợp nhiều chuỗi trong chuỗi bằng một lệnh?Ghép nối một chuỗi với các khả năng khác nhau bằng grep

Tôi biết grep có thể được sử dụng để khớp mẫu, nhưng sử dụng grep, tôi chỉ có thể kiểm tra một chuỗi tại một thời điểm. Tôi muốn biết nếu nhiều chuỗi có thể được sử dụng với một số lệnh khác hoặc với grep chính nó.

Trả lời

37

Vâng, bạn có thể. | trong mẫu grep có cùng ý nghĩa như or. Vì vậy, bạn có thể kiểm tra mẫu của mình bằng cách sử dụng "001|100|000" làm mẫu của bạn. Đồng thời, grep được vectorised, vì vậy tất cả những điều này có thể được thực hiện trong một bước: (. Trong trường hợp này người đầu tiên ba)

x <- c("1100", "0010", "1001", "1111") 
pattern <- "001|100|000" 

grep(pattern, x) 
[1] 1 2 3 

này trả về một chỉ số trong đó các vectơ của bạn chứa các mô hình phù hợp

Thỉnh thoảng thuận tiện hơn khi có một vectơ logic cho bạn biết phần tử nào trong vectơ của bạn đã được khớp. Sau đó, bạn có thể sử dụng grepl:

grepl(pattern, x) 
[1] TRUE TRUE TRUE FALSE 

Xem ?regex để được giúp đỡ về biểu thức thông thường trong R.


Edit: Để tránh tạo ra mô hình bằng tay chúng ta có thể sử dụng paste:

myValues <- c("001", "100", "000") 
pattern <- paste(myValues, collapse = "|") 
+0

@andrie, điều này hoàn toàn rực rỡ, được giả định nó là không thể trong nhiều năm, trong khi nó chỉ là một regex đơn giản,

+4

@DavidArenburg :-) Tôi đã học được từ kinh nghiệm cay đắng rằng không có gì là không thể trong R. Nó luôn luôn chỉ là một câu hỏi làm sao! – Andrie

2

Sử dụng đối số -e để thêm các mẫu khác:

echo '1100' | grep -e '001' -e '110' -e '101' 
+2

Tôi xin lỗi, nhưng tôi quên đề cập đến rằng tôi muốn thực hiện điều này trong R. – Narayani

+0

điều này rất hữu ích. – marbel

6

Dưới đây là một giải pháp sử dụng stringr gói

require(stringr) 
mylist = c("1100", "0010", "1001", "1111") 
str_locate(mylist, "000|001|100") 
1

Bạn cũng có thể sử dụng toán tử %like% từ data.table thư viện.

library(data.table) 

# input 
    x <- c("1100", "0010", "1001", "1111") 
    pattern <- "001|100|000" 

# check for pattern 
    x %like% pattern 

> [1] TRUE TRUE TRUE FALSE 
+0

Lưu ý rằng '% like%' chỉ là một trình bao bọc cho 'grepl', kiểm tra'?% Like% '" Đối số: ... \t pattern \t Chuyển sang grepl. ". Ít nhất lên đến 'data.table' phiên bản 1.10.4-2. –

1

Nếu bạn muốn vector logic thì bạn nên kiểm tra stri_detect chức năng từ stringi gói. Trong trường hợp bạn mô hình là regex, vì vậy sử dụng này một:

stri_detect_regex(x, pattern) 
## [1] TRUE TRUE TRUE FALSE 

Và một số tiêu chuẩn:

require(microbenchmark) 
test <- stri_paste(stri_rand_strings(100000, 4, "[0-1]")) 
head(test) 
## [1] "0001" "1111" "1101" "1101" "1110" "0110" 
microbenchmark(stri_detect_regex(test, pattern), grepl(pattern, test)) 
Unit: milliseconds 
          expr  min  lq  mean median  uq  max neval 
stri_detect_regex(test, pattern) 29.67405 30.30656 31.61175 30.93748 33.14948 35.90658 100 
      grepl(pattern, test) 36.72723 37.71329 40.08595 40.01104 41.57586 48.63421 100 
0

Xin lỗi vì làm cho này một câu trả lời additonal, nhưng nó là quá nhiều dòng cho nhận xét.

Tôi chỉ muốn nhắc nhở rằng số lượng mục có thể được dán cùng nhau qua paste(..., collapse = "|") để được sử dụng làm mẫu khớp duy nhất bị giới hạn - xem bên dưới. Có lẽ ai đó có thể biết chính xác giới hạn ở đâu? Phải thừa nhận rằng con số có thể không thực tế, nhưng tùy thuộc vào nhiệm vụ được thực hiện nó không hoàn toàn bị loại trừ khỏi những cân nhắc của chúng tôi.

Đối với số lượng mặt hàng thực sự lớn, cần có vòng lặp để kiểm tra từng mục của mẫu.

set.seed(0) 
samplefun <- function(n, x, collapse){ 
    paste(sample(x, n, replace=TRUE), collapse=collapse) 
} 

words <- sapply(rpois(10000000, 8) + 1, samplefun, letters, '') 
text <- sapply(rpois(1000, 5) + 1, samplefun, words, ' ') 

#since execution takes a while, I have commented out the following lines 

#result <- grepl(paste(words, collapse = "|"), text) 

# Error in grepl(pattern, text) : 
# invalid regular expression 
# 'wljtpgjqtnw|twiv|jphmer|mcemahvlsjxr|grehqfgldkgfu| 
# ... 

#result <- stringi::stri_detect_regex(text, paste(words, collapse = "|")) 

# Error in stringi::stri_detect_regex(text, paste(words, collapse = "|")) : 
# Pattern exceeds limits on size or complexity. (U_REGEX_PATTERN_TOO_BIG) 
Các vấn đề liên quan