2013-09-25 55 views
4

我正在嘗試使用正則表達式編寫程序來清理一些數據。假設我的房間名稱中有一個字母和一個數字。在最終的輸出中,我需要使用「完整字符串(不包括字母&數字)+字母+數字」模式輸出房間名稱,如下例所示。但是,到目前爲止我寫的正則表達式,我得到了非常糟糕的結果,這些結果在我的消息的底部。出於某種原因,它會在某些行上放置字母和字符,即使輸入數據中可能沒有。謝謝。正則表達式重新排序字段中的字符串

編輯:我編輯了輸入數據。我想概括一下代碼以獲取任意數量的字符串,而不僅僅是單個單詞「ROOM」。

# the pattern should be "the full string (excluding letter & number) + letter + number". For example: 
ATLANTA ROOM 
ATLANTA ROOM 3 
NEW YORK ROOM A 2 
ROOM A 4 
THE BIG AWESOME ROOM B 
ROOM B 4 
GEORGETOWN ROOM B 2 
NEW YORK ROOM C 2 
NEW YORK ROOM C 
LOS ANGELES ROOM E 2 

# program to clean with regular expressions. there could be multiple spaces between words 
dd <- c("ATLANTA ROOM ", 
    " ATLANTA ROOM 3", 
    "NEW YORK A ROOM 2", 
    "4 ROOM A", 
    "THE BIG AWESOME ROOM B", 
    " ROOM 4 B", 
    "GEORGETOWN B 2 ROOM ", 
    " C NEW YORK ROOM 2", 
    "NEW YORK ROOM C", 
    "LOS ANGELES ROOM 2 E") 

m_char_num <- regexpr("(\\<A|B|C|D|E|1|2|3|4\\>)", dd) 
m_char <- regexpr("(\\<A|B|C|D|E\\>)", dd) 
m_num <- regexpr("(\\<1|2|3|4\\>)", dd) 

(dd2 <- paste(gsub("(+)", " ", 
        gsub("(^ +)|(+$)", "", 
         gsub("(\\<A|B|C|D|E|1|2|3|4\\>)", "", dd))), 
       regmatches(dd, m_char), regmatches(dd, m_num), sep = " ")) 

# actual output from the program 
"TLANTA ROOMA3", 
"TLANTA ROOMA2", 
"NW YORK ROOMA4", 
"ROOMA4", 
"TH IG WSOM ROOME2", 
"ROOMB2", 
"GORGTOWN ROOMB2", 
"NW YORK ROOMC3", 
"NW YORK ROOMC2", 
"LOS NGLS ROOMA4" 
+1

貌似recy保守規則正在絆倒你。 「長度(dd)」與「長度(regmatches(dd,m_char))」不同,因爲regmatches省略了找不到匹配的位置。 –

回答

4

下面是一個嘗試:

sub(' $', '', # clean up spaces at the end 
    gsub(' +', ' ', # clean up double spaces 
     # rearrange letter and numbers 
     sub('^([A-Z]?)([0-9]*)([A-Z]?)$', 'ROOM \\1\\3 \\2', 
      gsub(' |ROOM', '', dd) # remove spaces and ROOM 
      ) 
     ) 
    ) 
#[1] "ROOM"  "ROOM 3" "ROOM A 2" "ROOM A 4" "ROOM B" "ROOM B 4" "ROOM B 2" 
#[8] "ROOM C 2" "ROOM C" "ROOM E 2" 

下面是經編輯OP相同的邏輯和評論如下(假設房間名稱是具有至少3個字母和單詞最多2個字母的房間名稱):

gsub('(^ | $)', '', # clean up spaces in front or end 
    gsub(' +', ' ', # clean up double spaces 
      # extract room name and put it in front of the letter and number 
      paste(gsub('\\b([A-Z][A-Z]?|[0-9]+)\\b', '', dd, perl = T), 
       sub('^([A-Z]+)?([0-9]*)([A-Z]+)?$', '\\1\\3 \\2', 
        gsub(' |\\w\\w\\w+', '', dd) # remove spaces and words 
        ) 
       ) 
     ) 
    ) 
+0

我喜歡這個實現。它簡短明瞭,但我希望能夠將代碼概括爲使用任何字符串/ s,而不僅僅是單個單詞「ROOM」。我通過更改輸入數據編輯了我的最初問題。 – vatodorov

+0

@vatodorov請參閱編輯 – eddi

+0

你能否改變正則表達式來接受兩個字符的房間?例如 - AD,BB,CD,TX。謝謝。 – vatodorov

2

因此,發生了什麼是你的程序只有8個字母,所以不是插入「」或NA,而是回收它們。

這裏是一個修正:

m_char_num <- regexpr("(\\<A|B|C|D|E|1|2|3|4\\>)", dd) 
m_char <- regexpr("(\\<A|B|C|D|E\\>)", dd) 
m_num <- regexpr("(\\<1|2|3|4\\>)", dd) 

numbers <- rep("", length(dd)) 
numbers[m_num>0] <- regmatches(dd, m_num) 

letters <- rep("", length(dd)) 
letters[m_char>0] <- regmatches(dd, m_char) 

output <- trim(paste("ROOM", letters, numbers)) 

[1] 「房間」 「ROOM 3」 「ROOM A 2」, 「ROOM A 4」 「ROOM B」 「ROOM B 4」, 「ROOM B 2」 「ROOM的C 2」, 「ROOM C」
[10] 「室E 2」

0

嘗試這種情況:

library(gsubfn) 

# extract numbers (num) and room letters (char) 
num <- sapply(strapplyc(dd, "\\d|$"), paste, collapse = "") 
char <- sapply(strapplyc(dd, "[A-D]|$"), paste, collapse = "") 

# put back together and sort 
out <- sort(paste("ROOM", char, num)) 

# trim spaces (optional) 
out <- gsub(" +", " ", sub(" *$", "", out)) 

> out 
[1] "ROOM"  "ROOM 2" "ROOM 3" "ROOM A 2" "ROOM A 4" "ROOM B" 
[7] "ROOM B 2" "ROOM B 4" "ROOM C" "ROOM C 2" 

UPDATE:小的改進

相關問題