字符串生成器问题

本文关键字:问题 字符串 | 更新日期: 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;
}