2013-06-26 32 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; 
}