【问题标题】:Creating strings from a template by replacing placeholders by all permutations of an input set通过用输入集的所有排列替换占位符从模板创建字符串
【发布时间】:2020-10-02 16:06:39
【问题描述】:

我想做一个简单的字符串生成器。

用户输入字符串的“模板”。模板中的任何位置都可以有占位符。 然后他输入可能适合字符串中任何占位符的字符。 它应该如何工作:

输入:

a.b.
123

输出:

[
"a1b1", "a1b2", "a1b3",
"a2b1", "a2b2", "a2b3",
"a3b1", "a3b2", "a3b3"
]

我找到了一些我的旧python代码,但我完全不明白。

我将输入字符串拆分为字符串数组和点数组。 然后我尝试只增加点,每次都以正确的方式连接这两个数组。 但是我发现了一个新的麻烦。

string[] splitted = kt_NonCur.Split('.');   // array of constant strings
char[] nch = new char[splitted.Length - 1]; // array of new chars (generated)
char lgc = goodLetters.Last( );    // last good char
for( int i = 0; i < nch.Length - 1; i++ ) // set up all nch to first letter
    nch[i] = goodLetters[0];
while( nch.Last( ) != lgc ) {  // until last nch is set to last good char
    outputData.Add($"{concatsplit(splitted, nch)}"); // concatsplit(s,n) concatenates two arrays into string
    nch[0] = up(nch[0]); // up(char) gets next character from goodLetters. If there is no next, it returns first letter.
    if( nch[0] == goodLetters[0] ) {
        nch[1] = up(nch[1]);    
        if(nch[1] == goodLetters[0]){
                nch[2] = up(nch[2]);
//                          .
//                              .
//                                  .
        }
    }
}

问题是:我正面临两难境地。要么找到更好的方法,要么限制占位符的数量,这样代码阶梯就不会太长。当然我会添加一些代码来检查它是否是最后一个并停止为其他人执行代码,但我仍然必须制作

【问题讨论】:

  • 要搜索的关键字是“排列”。 .Net 中没有此功能,但您应该能够找到一个库来帮助生成它们。
  • 如果输入是:a.b.1 会发生什么
  • 添加到@JoelCoehoorn 评论,这里的确切术语将是“重复排列”(因为相同的替换字符可以在输出中多次出现。

标签: c# string generator


【解决方案1】:

基于this post接受的回答:

public static IEnumerable<string> Combinations(string template, string str, char placeholder)
{
    int firstPlaceHolder = template.IndexOf(placeholder);   
    if (firstPlaceHolder == -1)     
        return new string[] { template };

    string prefix = template.Substring(0, firstPlaceHolder);    
    string suffix = template.Substring(firstPlaceHolder + 1);   
       
    var recursiveCombinations = Combinations(suffix, str, placeholder);

    return
        from chr in str
        from recSuffix in recursiveCombinations
        select prefix + chr + recSuffix;
 }

用法:

List<string> combinations = Combinations("a.b.", "123", '.').ToList();

【讨论】:

    【解决方案2】:

    您可以这样看待您的问题:如果您的输入字符串中有 P 个占位符并且替换字符的数量是 R,则在每一步构建您需要的每个可能的输出字符串 P 个数字 [0...R- 1](然后可以用作替换字符列表的索引)。嗯,这就是以 R 为基数的 P 位整数的定义。

    所以让我们编写一个帮助类来表示这些整数:

    class NDigitNumber
    {
        int[] _digits;
        int _base;
    
        // construct an integer with the specified numer of digits in the specified base
        public NDigitNumber(int digits, int @base)
        {
            _digits = new int[digits];
            _base = @base;
        }
    
        // get the digit at the specified position
        public int this[int index] => _digits[index];
    
        // increment the number, returns false on overflow
        public bool Increment()
        {
            for (var pos = 0; pos < _digits.Length; pos++)
            {
                if (++_digits[pos] < _base)
                    break;
                if (pos == _digits.Length-1)
                    return false;
                for (var i = 0; i <= pos; i++)
                    _digits[i] = 0;
            }
            return true;
        }
    }
    

    Increment 方法的工作方式类似于mechanical counter devices,其中每个数字轮从其最大数字旋转到下一个数字时,会将自身和所有较低的数字轮重置为 0,并递增下一个较高的数字。

    然后我们只需要遍历所有可能的此类整数即可获得所需的输出:

    var input = "a.b.";
    var placeholder = '.';
    var replacements = new[] { '1', '2', '3' };
    
    // determine positions of placeholder in string
    var placeholderPositions = new List<int>();
    for (var i = 0; i < input.Length; i++)
    {
        if (input[i] == placeholder)
            placeholderPositions.Add(i);
    }
    
    // iterate over all possible integers with
    // placeholderPositions.Count digits
    // in base replacements.Length
    var number = new NDigitNumber(placeholderPositions.Count, replacements.Length);
    do
    {
        var result = new StringBuilder(input);
        for (var i = 0; i < placeholderPositions.Count; i++)
            result[placeholderPositions[i]] = replacements[number[i]];
        Console.WriteLine(result.ToString());
    } while(number.Increment());
    

    输出:

    a1b1
    a2b1
    a3b1
    a1b2
    a2b2
    a3b2
    a1b3
    a2b3
    a3b3
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-02
      • 2020-06-09
      • 2021-09-26
      • 2012-05-11
      • 1970-01-01
      相关资源
      最近更新 更多