2017-08-11 17 views
2

比方說,我有一個字符串,我想檢查它是否與任何可能(隨機)順序中的另一個字符串匹配。舉例來說,假設我有一個字符串s,我要檢查它是否以隨機順序一致"ONE"(==下列之一:ENO|EON|NEO|NOE|OEN|ONE,但不是EEE;EEN;EEO;等)正則表達式與任何隨機順序中的字符完全匹配,沒有重複的字符

在更一般的描述:我正在尋找一個正則表達式,以隨機順序匹配字符串,只有該字符串的給定字符(這意味着字符串本身可以包含重複字符,如SEVEN,但應該在隨機匹配中恰好使用兩個E ,而不多或少)。

我知道我可以使用文字ENO|EON|NEO|NOE|OEN|ONE匹配ONE,與同爲TWO通過NINE,但這是太長..
我也知道我可以匹配的一切,包括像這樣[ONE]{3}重複的字符,但隨後它也會錯誤地匹配EEE,EEN等。

我知道我也可以創建一個循環來生成所有這些不同的排列,並將它們與|分隔符一起附加在一起。我認爲這也可能是這種情況下的有效解決方案。但如果這是可能的正則表達式我想知道以及我自己的知識。哦,即使它是循環的,我也不希望它太長(因爲我實際上是因爲代碼高爾夫的挑戰,你在哪裏以儘可能少的字節解決某個挑戰)。

+0

我不認爲有一個簡單的方法與「正常」的正則表達式來做到這一點 - 聽起來像是你需要PERFO RM模糊匹配,這AFAIK沒有一個標準的正則表達式引擎的支持 – UnholySheep

+0

什麼是錯的只是在做類似'因爲如果(計數(C,「ONE」)!=計數(C,STR)(字符在「ONE」 C)返回false;'?這樣,你不必爲每個單詞都寫一個正則表達式。 (也,這基本上是一個更有效的版本,什麼樣的正則表達式將編譯也是閒着) – Tezra

+0

@Tezra這的確是一個不錯的選擇也是如此。儘管在這種情況下優先使用正則表達式,但由於我忘記了在問題中提到的內容。它應該匹配完整的String的一部分。所以一個字符串可能是這樣的:''ENOWOT「',它應該返回'」12「'。我沒有提到這一點,因爲我的頭腦中已經有了一個解決策略,這需要像_Casimir和Hippolyte_提供的正則表達式。 [這裏是Codegolf挑戰順便說一句,如果誰不知道我想要什麼來實現的。(https://codegolf.stackexchange.com/questions/131852/the-original-number) –

回答

4

您可以將條件放在預覽中。對於一個:

\b(?=\w*O)(?=\w*N)(?=\w*E)[ONE]{3}\b 

七:

\b(?=[ONE]{3}\b)(?=\w*O)(?=\w*N)\w*E\w* 

\b(?=\w*S)(?=\w*E\w*E)(?=\w*V)(?=\w*N)[SEVN]{5}\b 

爲了提高大文本的性能,可以在模式的開始測試信件和長度

或:

\b(?=[SEVN]{5}\b)(?=\w*S)(?=\w*E\w*E)(?=\w*V)\w*N\w* 

這樣,包含其他字母或長度不合適的單詞將被快速丟棄。

你也可以把效率較低的條件下底:

\b(?=[SEVN]{5}\b)(?=\w*S)(?=\w*V)(?=\w*N)\w*E\w*E\w* 

要完成,您還可以使用否定的字符類減少回溯:

\b(?=[SEVN]{5}\b)(?=[^\WS]*S)(?=[^\WV]*V)(?=[^\WN]*N)[^\WE]*E[^\WE]*E\w* 

或使用其他字母:

\b(?=[SEVN]{5}\b)(?=[EVN]*S)(?=[SEN]*V)(?=[SEV]*N)[SVN]*E[SVN]*E\w* 
+2

謝謝!通過提供所有這些其他替代方案來提供很好的答案使用正則表達式,在我的經驗中,對於同樣的問題,總是有多種解決方案,並且很高興看到你已經給出了更好的性能替代方案。 +1並被接受。 :) –

0

是的,你可以建立你的正則表達式來使它像這樣^(?=[ONE]{3}$)(?=.*O).*(?=.*N).*(?=.*E).*$regex demo,所以你可以使用這樣的事情:

public static void main(String[] args) { 
    String[] strings = new String[]{"ENOE", "ENO", "EON", "NEO", "NOE", "OEN", 
     "ONE", "OOO"}; 
    Main m = new Main(); 
    String word = "ONE";// This can be any word you want to matche 
    String regex = m.getPattern(word); 
    System.out.println(regex); 
    for (String s : strings) { 
     if (s.matches(regex)) { 
      System.out.println("matches : " + s); 
     } else { 
      System.out.println("Not matches : " + s); 
     } 
    } 
} 

// I use Java 8 to create the pattern it is more helpful 
private String getPattern(String word) { 
    StringBuilder pattern = new StringBuilder(); 
    //^(?=[ONE]{3}$) 
    pattern.append("^(?=[").append(word).append("]{").append(word.length()).append("}$)"); 
    Arrays.asList(word.split("")).stream() 
      .map(t -> "(?=.*" + t + ").*") 
      .forEach(pattern::append); 
    pattern.append("$"); 
    return pattern.toString();// result (?=.*O).*(?=.*N).*(?=.*E).* 
} 

輸出

Not matches : ENOE 
matches : ENO 
matches : EON 
matches : NEO 
matches : NOE 
matches : OEN 
matches : ONE 
Not matches : OOO 
+0

這匹配OOO – marvel308

+0

現在@ marvel308呢? –

+0

比賽ONEE您可以通過限制長度 – marvel308

1

我認爲,正則表達式不能做那。

使用map< Integer,Integer>來計數你的字符,並驗證,或者只是一個數組(更快)。

+0

或'Map '也許? –

+0

@MauricePerry。是的! –

0

如果字符串中的字符是唯一的

^(?=[ONE]{3}$)(?=.*O).*(?=.*N).*(?=.*E).*$ 

你可以看到一個演示here

正則表達式的工作原理基本上它匹配如下enter image description here

爲此,您可以使用下面的正則表達式一個3個字母的單詞,由來自的字母組成[ONE]並確保所有3個字符出現在結果字符串中

+0

與SEVEN無效... –

+0

是的,這就是爲什麼我指定了獨特的字符 – marvel308

+0

如果包含某種解釋,這個答案會更好。 –

相關問題