2012-06-20 28 views
3

例如:如何匹配X%2串(即> 90%匹配)

S1: "some filename contains few words.txt"
S2: "some filename contains few words - draft.txt"
S3: "some filename contains few words - another draft.txt"
S4: "some filename not contains few words.txt"

需要注意的是,我可以得到S2或S3的第一個字符串和其他字符匹配。

編輯:我有「主」字符串,我需要找到匹配。

可以說,在第一輪中,我發現了錯別字。

現在我只能匹配整個單詞。

我希望能夠確定7個單詞中的5個是匹配的,或者是10箇中的7個。「X出Y」的確切數目不太重要。

重要的是如何發現差異是X詞,而不是他們在句子中的詞。

謝謝

+0

添加適當的語言標籤。 – dirkgently

+0

不知道這是否可以用RegEx實現,但看看Levenshtein距離算法:http://www.dotnetperls.com/levenshtein –

+0

這不適合正則表達式;更像是找到常見的子串。 – Joey

回答

6

這不是一個正則表達式問題。

您不指定語言,但如果您使用的是java,則StringUtils的方法有getLevenshteinDistance。從javadocs:

找到兩個字符串之間的Levenshtein距離。

這是將一個字符串更改爲 另一個需要更改的次數,其中每個更改都是單個字符修改 (刪除,插入或替換)。

用法:

int distance = StringUtils.getLevenshteinDistance(
    "some filename contains few words.txt", 
    "some filename not contains few words.txt" 
); 

要按一定比例匹配,你必須決定哪些字符串是「主」,因爲輸入字符串的長度可以不同:該distance可能是全部刪除,所以"cat""cataract"的距離爲5。確定「90%匹配」應該是什麼也有點困難。看看我們的cat的例子;在「白內障」中找到100%的字符串「貓」,但它們不完全相同。您必須根據您的使用情況決定這些規則。

更新

如果你的「差異化」應以單詞爲基礎,這將會是比較容易拆就單詞邊界的字符串,並從所得的字構造一個Map以計數的每個字。比較每個字符串生成的地圖應該給你一個粗略的「相似性」度量。例如:

public HashMap<String, Integer> countWords(String str) { 
    HashMap<String, Integer> counts = new HashMap<String, Integer>(); 
    for(String s : str.split("\\s+")) { 
     if(!s.isEmpty()) { 
      if(counts.containsKey(s)) { 
       counts.put(s, counts.get(s) + 1); 
      } else { 
       counts.put(s, 1); 
      } 
     } 
    } 
    return counts; 
} 

// ... 

String s1 = "some filename contains few words.txt"; 
String s2 = "some filename not contains few words.txt"; 
HashMap<String, Integer> s1Counts = countWords(s1); 
HashMap<String, Integer> s2Counts = countWords(s2); 
// assume s1 is "master" string, count the total number of words 
int s1Total = 0, s2Total = 0; 
for(Integer i : s1Counts.values()) { 
    s1Total += i; 
} 
// iterate over words in s1, find the number of matching words in s2 
for(Map.Entry<String, Integer> entry : s1Counts.entrySet()) { 
    if(s2Counts.containsKey(entry.getKey())) { 
     if(s2Counts.get(entry.getKey()) >= entry.getValue()) { 
      s2Total += entry.getValue(); 
     } else { 
      s2Total += s2Counts.get(entry.getKey()); 
     } 
    } 
} 
// result 
System.out.println(s2Total + " out of " + s1Total + " words match."); 
+0

我想說,你應該在這裏尋找普通的子串而不是Levenshtein距離。 – Joey

+0

感謝您的麻煩。在發佈問題之前,我花了好幾個小時來思考它。我知道「主」字符串,我需要猜測用戶希望看到「相似」的內容。 –

+0

@Joey我會查找它。 –