2015-11-02 2 views
1

Я ищу эффективный способ в R, чтобы указать, может ли одна строка быть аббревиатурой для другой. Основной подход, который я принимаю, - это увидеть, будут ли буквы в более короткой строке появляться в том же порядке в более длинной строке. Например, если моя более короткая строка была «abv», а моя более длинная строка была «аббревиатурой», я бы хотел получить положительный результат, тогда как если бы моя более короткая строка была «avb», я бы хотел получить отрицательный результат. У меня есть функция, которую я собрал вместе, но это похоже на довольно неэлегантное решение, и я подумал, что может не хватать магии регулярных выражений. Я также посмотрел на функцию «stringdist» R, но я не нашел ничего похожего на это. Вот моя функция:R искать аббревиатуру в полной строке

# This function computes whether one of the input strings (input strings x and y) could be an abbreviation of the other 
# input strings should be all the same case, and probably devoid of anything but letters and numbers 
abbrevFind = function(x, y) { 

    # Compute the number of characters in each string 
    len.x = nchar(x) 
    len.y = nchar(y) 

    # Find out which string is shorter, and therefore a possible abbreviation 
    # split each string into its component characters 
    if (len.x < len.y) { 

    # Designate the abbreviation and the full string 
    abv = substring(x, 1:len.x, 1:len.x) 
    full = substring(y, 1:len.y, 1:len.y) 

    } else if (len.x >= len.y) { 

    abv = substring(y, 1:len.y, 1:len.y) 
    full = substring(x, 1:len.x, 1:len.x) 

    } 

    # Get the number of letters in the abbreviation 
    small = length(abv) 

    # Set up old position, which will be a comparison criteria 
    pos.old = 0 

    # set up an empty vector which will hold the letter positions of already used letters 
    letters = c() 

    # Loop through each letter in the abbreviation 
    for (i in 1:small) { 

    # Get the position in the full string of the ith letter in the abbreviation 
    pos = grep(abv[i], full) 
    # Exclude positions which have already been used 
    pos = pos[!pos %in% letters] 
    # Get the earliest position (note that if the grep found no matches, the min function will return 'Inf' here) 
    pos = min(pos) 
    # Store that position 
    letters[i] = pos 

    # If there are no matches to the current letter, or the current letter's only match is earlier in the string than the last match 
    # it is not a possible abbreviation. The loop breaks, and the function returns False 
    # If the function makes it all the way through without breaking out of the loop, the function will return true 
    if (is.infinite(pos) | pos <= pos.old) {abbreviation = F; break} else {abbreviation = T} 

    # Set old position equal to the current position 
    pos.old = pos 

    } 

    return(abbreviation) 

} 

Спасибо за любую помощь!

+0

Это сложный вопрос. Вы можете попытаться использовать 'base :: abbreviate', чтобы сократить условия поиска, а затем использовать' stringdist' для поиска ближайших совпадений. –

ответ

1

, что о чем-то вроде этого, где вы в основном принимают каждый символ и добавить опцию, чтобы соответствовать любой буквы 0 или более раз между каждым ([a-z]*?)

f <- Vectorize(function(x, y) { 
    xx <- strsplit(tolower(x), '')[[1]] 
    grepl(paste0(xx, collapse = '[a-z]*?'), y) 
    ## add this if you only want to consider letters in y 
    # grepl(paste0(xx, collapse = sprintf('[%s]*?', tolower(y))), y) 
}, vectorize.args = 'x') 

f(c('ohb','hello','ob','ohc'), 'ohbother') 
# ohb hello ob ohc 
# TRUE FALSE TRUE FALSE 

f(c('abbrev','abb','abv', 'avb'), 'abbreviation') 
# abbrev abb abv avb 
# TRUE TRUE TRUE FALSE 
+0

Это прекрасно. Как я уже сказал, не хватает магии регулярных выражений ... Спасибо! – chtongueek

0

Не так не хватает ответа, но использует рекурсию (рекурсии изящны, верно?: p)

#Just a library I prefer to use for regular expressions 
library(stringr) 

#recursive function 
checkAbbr <- function(abbr,word){ 
    #Go through each letter in the abbr vector and trim the word string if found 
    word <- substring(word,(str_locate(word,abbr[1])[,1]+1)) 
    abbr <- abbr[-1] 

    #as long as abbr still has characters, continue to loop recursively 
    if(!is.na(word) && length(abbr)>0){ 
    checkAbbr(abbr,word) 
    }else{ 
    #if a character from abbr was not found in word, it will return NA, which determines whether the abbr vector is an abbreviation of the word string 
    return(!is.na(word)) 
    } 
} 


#Testing cases for abbreviation or not 
checkAbbr(strsplit("abv","")[[1]],"abbreviation") #FALSE 
checkAbbr(strsplit("avb","")[[1]],"abbreviation") #FALSE 
checkAbbr(strsplit("z","")[[1]],"abbreviation") #FALSE 

 Смежные вопросы

  • Нет связанных вопросов^_^