2013-06-26 63 views
-2

我想寫一個返回字符串的方法。到現在爲止還挺好。然而,字符串的創建非常複雜。我有3個字符串列表 - 第一個有155個條目,第二個是-9,第三個是21.我想要我的方法,如果調用足夠的時間(155 * 9 * 21)從3返回所有可能的值組合列表(基本上這個方法應該保持它被調用的次數,並且每次只返回一個組合)。任何想法如何實現?我有155 * 9 * 22的可能組合。第一次調用該方法時,應該使用List1(0),List2(0),List3(0)。之後,在接下來的21次迭代中,第三個列表的索引僅被更改。一旦第三個列表中的所有元素都被用來增加第二個列表的索引,依此類推。字符串發生器問題

一旦該方法產生了所有可能的組合(155 * 9 * 22),我希望它從頭開始。

+0

可能你應該嘗試'yield return':[example](http://msdn.microsoft.com/en-us/library/vstudio/9k7k7cf0.aspx) –

+0

就像三個for循環一樣簡單;每個循環中的每個單詞都會打印出結果 – 2013-06-26 15:52:44

回答

1

使用好的舊模數運算符。可能可以優化更多。

public class Generator 
{ 
    private int index = 0; 
    private List<string> list1 = new List<string> { "a", "b" }; 
    private List<string> list2 = new List<string> { "c", "d" }; 
    private List<string> list3 = new List<string> { "e", "f", "g" }; 

    public string Next() 
    { 
     int indexList3 = index % list3.Count; 
     int indexList2 = (index/list3.Count) % list2.Count; 
     int indexList1 = (index/(list2.Count * list3.Count)) % list1.Count; 

     IncrementIndex(); 

     return list1[indexList1] + list2[indexList2] + list3[indexList3]; 
    } 

    private void IncrementIndex() 
    { 
     index++; 
     if (index > list1.Count*list2.Count*list3.Count) 
     { 
      index = 0; 
     } 
    } 
} 

所以第一個13次的結果(12個可能的組合),與

string result = string.Empty; 
Generator generator = new Generator(); 

for (int i = 0; i < 13; i++) 
{ 
    result += generator.Next() + "\n"; 
} 

輸出而獲得:

ace 
acf 
acg 
ade 
adf 
adg 
bce 
bcf 
bcg 
bde 
bdf 
bdg 
ace 
3

你可以只列舉所有可能的組合,這樣的:

public IEnumerable<String> generator() { 
     foreach (String item1 in List1) 
     foreach (String item2 in List2) 
      foreach (String item3 in List3) 
      yield return item1 + item2 + item3; 
    } 

    ... 

    foreach (String item in generator()) { 
    // Do something with generated strings 
    } 
+0

是的,但只有在調用該方法時纔會生成字符串,並且我的目標是通過使用某些索引來保持相同方法的效果。 – Andrey

+0

@Andrey閱讀我發佈在您的問題的評論中的鏈接 –

+0

是的,這將返回所有可能的組合。不過,我希望我的方法只在調用時才進行計算,並且要記住它到底有多遠。一種可能的方法是獲得所有的組合並只索引它們,但如果我決定擴展該方法(添加一個列表),那麼這將導致很多結果,這是不必要的內存使用。 – Andrey

1

你可以保持一個索引每個列表:

public IEnumerable<string> Permutations(string[][] lists, int start = 0) { 
    int[] position = new int[lists.Length]; 

    for(int i = lists.Length - 1; start > 0; i--) { 
     position[i] = start % lists[i].Length; 
     start /= lists[i].Length; 
    } 

    while(true) { 
     int i; 
     string current = string.Empty; 

     for(i = lists.Length - 1; i >= 0; i--) { 
      if(++position[i] == lists[i].Length) { 
       position[i] = 0; 
       current = lists[i][0] + current; 
      } else { 
       break; 
      } 
     } 

     if(i == -1) break; 

     while(i > -1) { 
      current = lists[i][position[i]] + current; 
      i--; 
     } 

     yield return current; 
    } 
} 

它需要一個地方開始,可選的,所以您只能保留一個整數並生成下一個項目。

雖然我沒有測試過這個。被警告! :)

1
public IEnumerable<string> List1 = new [] { "A", "B", "C" }; 
public IEnumerable<string> List2 = new [] { "1", "2", "3" }; 
public IEnumerable<string> List3 = new [] { "Z", "Y" }; 

public IEnumerator<string> StringEnumerator; 

public void InitializeEnumerator() 
{ 
    var stringEnumerable = List1.SelectMany(x => List2.SelectMany(y => List3.Select(z => x + y + z))); 

    StringEnumerator = stringEnumerable.GetEnumerator(); 
} 

public string GetNextString() 
{ 
    return StringEnumerator.MoveNext() ? StringEnumerator.Current : null; 
} 

只需撥打InitializeEnumerator(),那麼你會得到一個新的字符串出每個呼叫的到GetNextString()

InitializeEnumerator(); 
GetNextString(); //-> A1Z 
GetNextString(); //-> A1Y 
GetNextString(); //-> A2Z 
GetNextString(); //-> A2Y 
GetNextString(); //-> A3Z 
GetNextString(); //-> A3Y 
GetNextString(); //-> B1Z 

有它自動初始化並重新初始化它用完之後,像這樣修改GetNextString。

public string GetNextString() 
{ 
    if(StringEnumerator == null || !StringEnumerator.MoveNext()) 
    { 
     InitializeEnumerator(); 
     StringEnumerator.MoveNext(); 
    } 

    return StringEnumerator.Current; 
} 
+0

一旦它涵蓋了所有組合,如何使它從第一個迭代開始迭代? – Andrey

+0

再次調用InitializeEnumerator()。 –

+0

我修改了我的答案,以包含循環版本的GetNextString –

1

使用由Dmitry Bychenko所示的方法,就可以跟蹤如何遠遠在列表中:

// use his generator method 
public IEnumerable<String> generator() 
{ 
    ... 
} 

.... 

int counter = 0; 
foreach (String item in generator()) 
{ 
    // compute indexes 
    int ix_list3 = counter % List3.Count; 
    int ix_list2 = (counter/List3.Count) % List2.Count; 
    int ix_list1 = (counter/(List3.Count * List2.Count)); 

    // do something with item and indexes 
    ++counter; 
}