字符串生成器问题
本文关键字:问题 字符串 | 更新日期: 2023-09-27 18:20:10
我想写一个返回字符串的方法。到目前为止还不错。然而,字符串的创建相当复杂。我有3个字符串列表——第一个有155个条目,第二个有9个,第三个有21个。我希望我的方法被调用足够的次数(155*9*21),以返回3个列表中所有可能的值组合(基本上,这个方法应该计算它被调用的次数,每次只返回一个组合)。有什么想法可以实现吗?
我有155*9*22种可能的组合。第一次调用该方法时,应该使用List1(0)、List2(0)和List3(0)。之后,在接下来的21次迭代中,第三个列表的索引只发生了更改。一旦使用了第三个列表中的所有元素,就增加第二个列表的索引,依此类推
一旦该方法产生了所有可能的组合(155*9*22),我希望它从头开始。
您只需枚举所有可能的组合,如下所示:
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
}
使用了好的旧模运算符。可能可以进行更多优化。
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
您可以为每个列表保留一个索引:
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;
}
}
它有一个起始位置(可选),因此您可以只保留一个整数并生成下一个项。
不过我还没有测试过。请注意!:)
使用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;
}
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;
}