2011-03-22 122 views
1

我有一個小項目,我有一個輸入的句子它有可能爲用戶指定的變化:如何生成一整套字符串操作的組合?

The {small|big} car is {red|blue} 

上面是一個例句我想分成4個句子,像這樣:

  • 的小型車是紅色的
  • 大汽車是紅色的
  • 的小型車是藍色
  • 大汽車是藍色

我似乎無法繞過這個問題。也許有人可以幫我。

編輯 這是我最初的代碼

Regex regex = new Regex("{(.*?)}", RegexOptions.Singleline); 
MatchCollection collection = regex.Matches(richTextBox1.Text); 
string data = richTextBox1.Text; 

//build amount of variations 
foreach (Match match in collection) 
{ 
    string[] alternatives = match.Value.Split(new char[] { '|', '{', '}' }, StringSplitOptions.RemoveEmptyEntries); 
    foreach (string alternative in alternatives) 
    { 
     //here i get problems     
    } 
} 
+1

你嘗試過這麼遠嗎? ([提示](http://msdn.microsoft.com/en-us/library/ch45axte.aspx)) – 2011-03-22 14:06:05

+0

你看過正則表達式嗎? – 2011-03-22 14:07:48

+0

您錯過了作業標籤嗎? – 2011-03-22 14:08:41

回答

3

這聽起來像你需要爲這個動態笛卡爾功能。 Eric Lippert的blog post是爲響應Generating all Possible Combinations而寫的。

首先,我們需要解析輸入字符串:

Regex ex = new Regex(@"(?<=\{)(?<words>\w+(\|\w+)*)(?=\})"); 
var sentence = "The {small|big} car is {red|blue}"; 

然後輸入字符串應該修改string.Format樣的功能使用:

int matchCount = 0; 
var pattern = ex.Replace(sentence, me => 
{ 
    return (matchCount++).ToString(); 
}); 
// pattern now contains "The {0} car is {1}" 

那麼我們就需要找到所有匹配並申請Eric的優秀CartesianProduct擴展方法:

var set = ex.Matches(sentence) 
    .Cast<Match>() 
    .Select(m => 
     m.Groups["words"].Value 
      .Split('|') 
    ).CartesianProduct(); 

foreach (var item in set) 
{ 
    Console.WriteLine(pattern, item.ToArray()); 
} 

這將產生:

The small car is red 
The small car is blue 
The big car is red 
The big car is blue

,最後,該CartesianProduct方法(從here拍攝):

static IEnumerable<IEnumerable<T>> CartesianProduct<T>(
    this IEnumerable<IEnumerable<T>> sequences) 
{ 
    IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() }; 
    return sequences.Aggregate( 
    emptyProduct, 
    (accumulator, sequence) => 
     from accseq in accumulator 
     from item in sequence 
     select accseq.Concat(new[] {item}));     
} 
+1

這很美! – 2011-03-22 15:25:35

+0

哇。我認爲我越來越擅長c#,然後我看到這樣的答案提醒我我還有很多東西需要學習。 – 2011-03-23 14:26:37

-1
string color = SomeMethodToGetColor(); 
string size = SomeMethodToGetSize(); 

string sentence = string.Format("The {0} car is {1}", size, color); 
+0

我沒有看到此解決方案?在我的句子中沒有指定具體數量的變體,它可以不是或可以是幾個。 – 2011-03-22 14:12:42

+0

這個問題有4個句子。唯一的選擇是尺寸和顏色。我可能會誤解你的問題。你是說用戶用自由形式的文本輸入完整的句子嗎?即一個文本框來輸入整個句子? – 2011-03-22 14:22:53

+0

沒有冒犯,但這根本沒有幫助。 H4mm3rHead想要確定所有可能的組合。 – 2011-03-22 14:23:06

0

我提議輸入文本分成靜態和動態部分的有序列表。每個動態部分本身都包含一個存儲其值的列表和一個表示當前選定值的索引。該指數初始設定爲零。

要打印出所有可能的組合,首先必須實現一個方法,該方法使用動態部分的當前設置索引打印完整列表。對於第一次調用,所有索引都將設置爲零。

現在您可以遞增第一個動態部分的索引並打印完整列表。這會給你第一個變化。重複此操作,直到您打印剩餘動態部分的所有可能值。

+0

Off topic:這將是一個很好的練習,我的課程在C編程:) – 2011-03-22 14:19:31

0

考慮嵌套迭代循環。喜歡的東西...

foreach(string s in someStringSet) 
{ 
    foreach(string t in someOtherStringSet) 
    { 
     // do something with s and t 
    } 
} 
3
private void ExpandString(List<string> result, string text) 
    { 
     var start = text.IndexOf('{'); 
     var end = text.IndexOf('}'); 
     if (start >= 0 && end > start) 
     { 
      var head = text.Substring(0, start); 
      var list = text.Substring(start + 1, end - start - 1).Split('|'); 
      var tail = text.Substring(end + 1); 
      foreach (var item in list) 
       ExpandString(result, head + item + tail); 
     } 
     else 
      result.Add(text); 
    } 

使用像:

var result = new List<string>(); 
    ExpandString(result, "The {small|big} car is {red|blue}"); 
+0

尼斯和緊湊... – 2011-03-22 14:40:46

+0

測試和完美的作品。 – 2011-03-22 14:45:35

+0

{{是sentince的第一個字符! 改變「如果(開始> 0」到「> =」修復問題 – 2011-03-22 14:53:31

0

也許你正在尋找這樣的: 編輯的版本

static void Main(string[] args) 
{ 
    var thisstring = "The {Small|Big} car is {Red|Blue}";   
    string FirstString = thisstring.Substring(thisstring.IndexOf("{"), (thisstring.IndexOf("}") - thisstring.IndexOf("{")) + 1); 
    string[] FirstPossibility = FirstString.Replace("{", "").Replace("}", "").Split('|'); 
    thisstring = thisstring.Replace(FirstString, "[0]"); 
    string SecondString = thisstring.Substring(thisstring.IndexOf("{"), (thisstring.IndexOf("}") - thisstring.IndexOf("{")) + 1); 
    string[] SecondPosibility = SecondString.Replace("{", "").Replace("}", "").Split('|'); 
    thisstring = thisstring.Replace(SecondString, "{1}").Replace("[0]", "{0}"); 
    foreach (string tempFirst in FirstPossibility) 
    { 
     foreach (string tempSecond in SecondPosibility) 
     { 
      Console.WriteLine(string.Format(thisstring, tempFirst, tempSecond)); 
     } 
    } 
    Console.Read(); 
} 
1

如果你不」噸知道變化的數量,遞歸是你的朋友:

static public IEnumerable<string> permute(string template) 
{ 
    List<string> options; 
    string before; 
    string after; 
    if (FindFirstOptionList(template, out options, out before, out after)) 
    { 
     foreach (string option in options) 
     { 
      foreach (string permutation in permute(before + option + after)) 
      { 
       yield return permutation; 
      } 
     } 
    } 
    else 
    { 
     yield return template; 
    } 
} 

static public bool FindFirstOptionList(string template, out List<string> options, out string before, out string after) 
{ 
    before = string.Empty; 
    after = string.Empty; 
    options = new List<string>(0); 
    if (template.IndexOf('{') == -1) 
    { 
     return false; 
    } 
    before = template.Substring(0, template.IndexOf('{')); 
    template = template.Substring(template.IndexOf('{') + 1); 
    if (template.IndexOf('}') == -1) 
    { 
     return false; 
    } 
    after = template.Substring(template.IndexOf('}') + 1); 
    options = template.Substring(0, template.IndexOf('}')).Split('|').ToList(); 
    return true; 
} 

使用類似於danbystrom的解決方案,除了這個方法返回一個IEnumerable,而不是操縱調用的參數之一。當心語法錯誤等

static void main() 
{ 
    foreach(string permutation in permute("The {small|big} car is {red|blue}")) 
    { 
     Console.WriteLine(permutation); 
    } 
} 
0

像這樣的東西應該工作:

private void Do() 
{ 
    string str = "The {small|big} car is {red|blue}"; 

    Regex regex = new Regex("{(.*?)}", RegexOptions.Singleline); 

    int i = 0; 
    var strWithPlaceHolders = regex.Replace(str, m => "{" + (i++).ToString() + "}"); 

    var collection = regex.Matches(str); 

    var alternatives = collection.OfType<Match>().Select(m => m.Value.Split(new char[] { '|', '{', '}' }, StringSplitOptions.RemoveEmptyEntries)); 
    var replacers = GetReplacers(alternatives); 

    var combinations = new List<string>(); 
    foreach (var replacer in replacers) 
    { 
     combinations.Add(string.Format(strWithPlaceHolders, replacer)); 
    } 
} 

private IEnumerable<object[]> GetReplacers(IEnumerable<string[]> alternatives) 
{ 
    return GetAllPossibilities(0, alternatives.ToList()); 
} 

private IEnumerable<object[]> GetAllPossibilities(int level, List<string[]> list) 
{ 
    if (level == list.Count - 1) 
    { 
     foreach (var elem in list[level]) 
      yield return new[] { elem }; 
    } 
    else 
    { 
     foreach (var elem in list[level]) 
     { 
      var thisElemAsArray = new object[] { elem }; 
      foreach (var subPossibilities in GetAllPossibilities(level + 1, list)) 
       yield return thisElemAsArray.Concat(subPossibilities).ToArray(); 
     } 
    } 
    yield break; 
} 
相關問題