2013-03-26 33 views
1

我搜索了stackoverflow和網絡的類似問題,但我找不到我需要的解決方案。動態嵌套循環生成C#中數組元素的所有可能的組合#

我在編寫代碼列表生成器。

所以例如我有一個字符列表像List<char> { 'a', 'b', 'c' };

和我有幾個設置,如(int)minLength2(int)maxLength3

,我想這樣的輸出:

aa 
ab 
ac 
ba 
bb 
bc 
ca 
cb 
cc 

aaa 
aab 
aac 
aba 
abb 
abc 
aca 
acb 
acc 

baa 
bab 
bac 
bba 
bbb 
bbc 
bca 
bcb 
bcc 

caa 
cab 
cac 
cba 
cbb 
cbc 
cca 
ccb 
ccc 
在gereral我只想kreate多維循環

,但我有做動態,因爲diferent的minLength,最大長度& charList值這一點。

,所以我用「自調用函數」走出這樣的例子:

private void loop() { 
     for(int i = 0; i < num; i++) { 
      // stuff 
      loop(); 
     } 
    } 

到目前爲止,我已經取得了以下一串代碼,但在這個階段,我被卡住...:

Thread mainThread; 

    List<char> azlower; 
    List<char> azupper; 
    List<char> nullnine; 

    List<char> totalChars; 

    int totalNum; 

    int levelCounter; 

    bool running; 

    public Form1() { 
     InitializeComponent(); 
    } 

    private void init() { 
     azlower = new List<char> { 'a', 'b', 'c' , 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; 
     azupper = new List<char> { 'A', 'B', 'C' , 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' }; 
     nullnine = new List<char> { '0', '1', '2' /* , '3', '4', '5', '6', '7', '8', '9' */ }; 

     totalChars = new List<char>(); 

     running = false; 
    } 

    private void button1_Click(object sender, EventArgs e) { 
     if(!running) { 
      init(); 

      // Start 
      if(checkBoxAZ1.Checked) { 
       foreach(char character in azlower) { 
        totalChars.Add(character); 
       } 
      } 
      if(checkBoxAZ2.Checked) { 
       foreach(char character in azupper) { 
        totalChars.Add(character); 
       } 
      } 
      if(checkBox09.Checked) { 
       foreach(char character in nullnine) { 
        totalChars.Add(character); 
       } 
      } 
      if(checkBoxS.Checked && textBoxSpec.Text != "") { 
       char[] specArray = textBoxSpec.Text.ToCharArray(); 
       foreach(char character in specArray) { 
        totalChars.Add(character); 
       } 
      } 
      totalNum = totalChars.Count; 
      levelCounter = Int32.Parse(textBoxMinLength.Text); 
      mainThread = new Thread(new ThreadStart(run)); 
      button1.Text = "Stop"; 
      running = true; 
      mainThread.Start(); 
     } else { 
      mainThread.Abort(); 
      button1.Text = "Start"; 
      running = false; 
     } 
    } 

    private void run() { 
     for(int i = 0; i < totalNum; i++) { 
      Invoke((MethodInvoker) delegate { 
       write(totalChars[ i ].ToString()); 
       if(i == totalNum - 1 && levelCounter == Int32.Parse(textBoxMaxLength.Text)) { 
        write("\n"); 
       } 
      }); 
      if(levelCounter < Int32.Parse(textBoxMaxLength.Text)) { 
       levelCounter++; 
       run(); 
      } 
     } 
     return; 
    } 

    private void write(string line) { 
     richTextBox1.Text += line; 
    } 

,但上面的設置,我的代碼,輸出看起來是這樣的:

aabc 
bc 

我想我只是馬一個想法的錯誤,不是嗎?

so guys,you have anny suggestions for me?

我也看了看笛卡爾產品,但我認爲它不會只用一個陣列工作...

THX的任何幫助。

+0

可能重複http://stackoverflow.com/questions/5162254/all-可能的組合數組) – 2013-03-26 15:22:15

+2

@ReedCopsey雖然這個問題被標記爲C#所有的答案都是基於java的 – 2013-03-26 15:24:48

+0

@ScottChamberlain有[噸的重複](http://stackoverflow.com/search?q=combi國家+陣列+ C%23)這已經 - 例如我發佈的一個,但也http://stackoverflow.com/questions/7643885/different-combinations-of-an-array-c和http:// stackoverflow .com/questions/5777208/array-of-array-combinations在這個網站上搜索將很容易引起大量的愚弄 – 2013-03-26 15:27:31

回答

0

您可以使用回溯算法,代碼如下。輸出也包含在內以證明代碼有效。

如果您需要將參數傳遞給線程,請參閱this answer

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     const int MIN_LENGTH = 2; 
     const int MAX_LENGTH = 3; 
     static IList<string> vals; 
     static IList<string> results; 

    static void go(string cur) 
    { 
     if (cur.Length > MAX_LENGTH) 
     { 
      return; 
     } 
     if (cur.Length >= MIN_LENGTH && cur.Length <= MAX_LENGTH) 
     { 
      results.Add(cur); 
     } 

     foreach (string t in vals) 
     { 
      cur += t; 
      go(cur); 
      cur = cur.Substring(0, cur.Length - 1); 
     } 
    } 
    static int Main(string[] args) 
    { 
     vals = new List<string>(); 
     vals.Add("a"); 
     vals.Add("b"); 
     vals.Add("c"); 

     results = new List<string>(); 
     go(""); 
     results = results.OrderBy(x => x.Length).ToList(); 

     foreach (string r in results) 
     { 
      Console.WriteLine(r); 
     } 

     return 0; 
    } 
} 

輸出

aa 
ab 
ac 
ba 
bb 
bc 
ca 
cb 
cc 
aaa 
aab 
aac 
aba 
abb 
abc 
aca 
acb 
acc 
baa 
bab 
bac 
bba 
bbb 
bbc 
bca 
bcb 
bcc 
caa 
cab 
cac 
cba 
cbb 
cbc 
cca 
ccb 
ccc 
+0

當我在新線程中調用它時,如何在方法中傳遞屬性? – Ace 2013-03-26 15:31:43

+0

@Ace看到我的編輯解決方案。 – dcp 2013-03-26 15:36:42

+0

@Ace - 另外,我修改它以按照您請求的順序進行排序。 – dcp 2013-03-26 15:42:47

1

下面是將使用遞歸生成它的例子。

IEnumerable<string> GenerateCode(int length, int min, IEnumerable<char> chars) 
{ 
    if (length == 0) 
    { 
     yield return string.Empty; 
     yield break; 
    } 

    foreach (var mid in GenerateCode(length - 1, min, chars)) 
    { 
     foreach (var c in chars) 
     { 
      var t = mid + c; 
      if (length >= min) 
       Console.WriteLine(t); // replace with where you want to put the results 

      yield return t; 
     } 
    } 
} 

// now call this method: 
GenerateCode(3 /*max length*/, 2 /*min length*/, new [] { 'a', 'b', 'c' }); 

但是,除非這是一個練習,爲什麼你會產生所有可能的變化?如果您提供實際需求,可能會有更好的解決方案。

+0

再次,我有問題,我是調用函數作爲一個新的線程,在那裏我不能傳遞參數的方法 – Ace 2013-03-26 15:32:26

+0

是的,你可以。創建一個帶有單個'object'參數的新方法,使用'ParameterizedThreadStart',傳入'Tuple.Create(3,2,char [])',並將該方法中的對象參數轉換爲Tuple。 – 2013-03-26 15:34:32

+0

好吧,我會在下班後測試它。感謝這個例子。我也想注意到,我需要按照給定順序對輸出進行「排序」。 – Ace 2013-03-26 15:37:44

0
public static IEnumerable<IEnumerable<T>> Permutations<T>(IEnumerable<T> source) 
{ 
    if (source == null) 
     throw new ArgumentNullException("source"); 
    return permutations(source.ToArray()); 
} 

private static IEnumerable<IEnumerable<T>> permutations<T>(IEnumerable<T> source) 
{ 
    IEnumerable<T> enumerable = source as List<T> ?? source.ToList(); 
    var c = enumerable.Count(); 
    if (c == 1) 
     yield return enumerable; 
    else 
     for (int i = 0; i < c; i++) 
      foreach (var p in permutations(enumerable.Take(i).Concat(enumerable.Skip(i + 1)))) 
       yield return enumerable.Skip(i).Take(1).Concat(p); 
} 

private static IEnumerable<string> Subsets(char[] chars) 
{ 
    List<string> subsets = new List<string>(); 

    for (int i = 1; i < chars.Length; i++) 
    { 
     subsets.Add(chars[i - 1].ToString(CultureInfo.InvariantCulture)); 
     int i1 = i; 
     List<string> newSubsets = subsets.Select(t => t + chars[i1]).ToList(); 
     subsets.AddRange(newSubsets); 
    } 
    subsets.Add(chars[chars.Length - 1].ToString(CultureInfo.InvariantCulture)); 
    return subsets; 
} 
private static void Main() 
{ 
    char[] chars = new[]{'a','b','c'}; 
    var subsets = Subsets(chars); 
    List<string> allPossibleCombPerm = 
     subsets.SelectMany(Permutations).Select(permut => string.Join("", permut)).ToList(); 
    allPossibleCombPerm.ForEach(Console.WriteLine); 
} 
0

您可以使用下面的功能。 T是將被組合到字符串中的元素的類型(ToString()將在每個項目上被調用)。您可以選擇使用表示組合的字符串的前綴和分隔符,因此它們看起來像myprefix_A_1,myprefix_A_2等,其中_將是分隔符。

您必須使用level = 1和tmpList = null調用此函數。

public static IEnumerable<string> Combine<T>(string prefix, 
               string separator, 
               List<List<T>> collections, 
               int level, List<string> tmpList) 
    { 
     if (separator == null) 
      separator = ""; 

     if (prefix == null) 
      prefix = ""; 

     List<string> nextTmpList = new List<string>(); 
     int length = collections.Count(); 

     if (tmpList == null || tmpList.Count == 0) 
     { 
      tmpList = new List<string>(); 
      foreach (var ob in collections.Last()) 
       tmpList.Add(ob.ToString()); 
     } 

     if(length == level) 
     { 
      foreach (string s in tmpList) 
       nextTmpList.Add(prefix + separator + s.ToString()); 
      return nextTmpList; 
     } 


     foreach (var comb in tmpList) 
      foreach(var ob in collections[length - level - 1]) 
       nextTmpList.Add(ob.ToString() + separator + comb); 
     return Combine(prefix, separator, collections, level + 1, nextTmpList); 

    } 

實施例:

Combine<int>("G1", "_", new List<List<int>>() { new List<int>() { 1, 3}, new List<int>() {2, 4 } }, 1, null); 

OUTPUT:

G1_1_2  G1_3_2 G1_1_4 G1_3_4 
[陣列的所有可能的組合(指
相關問題