2013-10-20 116 views
1

我需要幫助查找部分單詞匹配。它應該返回匹配三個連續字母的單詞到目標。例如:Ruby部分單詞匹配

WORDS = ["born", "port" ,"cort", "mort"] 
find_match("corn", WORDS) => returns ["born", "cort"] 

應找到部分匹配"corn"。和「b orn」和「cor t」相匹配。

正則表達式可能不是解決此類問題的最佳選擇。如果您有其他想法,請隨時分享。

回答

6

你可以使用each_cons打造的子字符串數組:

'corn'.chars.each_cons(3).map(&:join) 
# ['cor', 'orn'] 

然後Regexp.union到數組轉換爲一個單一的正則表達式:

re = Regexp.union('corn'.chars.each_cons(3).map(&:join)) 

然後你就可以匹配re對數組元素:

WORDS.select { |w| w =~ re } 

推廣:

def find_match(word, words) 
    re = Regexp.union(word.chars.each_cons(3).map(&:join)) 
    words.select { |w| w =~ re } 
end 

我確定這個普通主題有很多變化。例如,你可以使用match_str形式的String#[],而不是一個正則表達式,我敢肯定有很多不同的方式來拉出長度的所有子3

+2

或'words.grep(re)' – Stefan

+0

@Stefan:很好。我很多都忘記了'grep'。 –

+0

謝謝,畝。這裏有很多對我來說很新鮮的東西,再加上@ Stefan的關於grep的提醒。我不知道each_con或Regexp.union。很有用。我將不得不更深入地研究Regexp的方法。 –

2

非正則表達式的解決方案:

WORDS = ["born", "port" ,"cort", "mort"] 

def find_match(w) 
    threes = (0..w.size-3).reduce([]) {|arr, i| arr << w[i,3]} 
    WORDS.select {|w| threes.select {|s| w.include?(s)}.any?} 
end 

find_match("corn") # => ["born", "cort"] 
find_match("cavort") # => ["port", "cort", "mort"] 
find_match("heart") # => [] 
  • 首先計算threes,長度爲3的所有子字符串w的數組。如果w = snort,這將是['sno', 'nor', 'ort'],其中w[0,3] = 'sno',w[1,3] = 'nor'w[2,3] = 'ort'
  • 接下來,請選擇WORDS中包含至少與threes中的字符串匹配的子字符串的字詞。

這方面有當然許多變體,如:

threes = []; (threes << w[0,3]; w.slice!(0)) while w.size > 2 

對於第二線之上,我最初試圖

threes.reduce([]) {|arr1, s| arr1 += WORDS.select {|w| w.include?(s)}} 

但這是有問題的,因爲在WORDS一個字可能會匹配w的多個3個字符的子字符串,在這種情況下,每個匹配都會包含arr1一次。