【问题标题】:Generating every possible combination between two alphanumeric string ranges生成两个字母数字字符串范围之间的所有可能组合
【发布时间】:2018-05-09 09:56:22
【问题描述】:

我正在使用 SAP Idocs,它的段可以包含成本中心参考范围。范围作为字符串的开始值和结束值给出。要将这些值存储在我的数据库中,我需要生成这些值之间存在的所有可能组合。

字符串是字母数字的,比如开始:D98C1 和结束:D9AZ3。单个字符序列首先是从 0 到 9 的数字,然后是从 A 到 Z 的字母。扩展需要在开始和结束之间生成所有可能的组合,比如说开始:A1 到结束:CA 将包含值@ 987654325@ to A9, AA to AZ, B0 to B9, BA to BZ, C0 to C9 and @987644

我完全坚持这一点,并且非常感谢一些关于如何实现它的指针。

编辑:

作为一个人,我会首先找到开始字符串和结束字符串之间不同的部分。我能做到,这很容易。所以对于上面的例子,那就是D9。然后我会一次遍历一个字符的起始字符串的可变部分,并改变字符串末尾的所有字符,遍历所有可能的字符,直到我到达结束字符串中的相应字符。

我只是被困住了。

我一开始是这样的:

readonly static char[] values = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToArray(); 

    static void Main(string[] args)
    {
        string from = "D3A0";

        string to = "D3AC";

        string root = new string(from.TakeWhile((c, i) => to.Length >= i && to[i] == c).ToArray());

        string from1 = from.Substring(root.Length);

        string to1 = to.Substring(root.Length);

        var output = new List<string>();

        for (int i = from1.Length - 1; i == 0; i--)
        {
            char startChar = from1[i];

            char endChar = to1[i];

            var remainingValues = values.SkipWhile(v => v != startChar)
                                        .TakeWhile(v => v != endChar)
                                        .ToList();

            foreach (char v in remainingValues)
            {
                string currentValue = from1.Remove(i) + v;

                output.Add(currentValue);
            }

            if (output.Contains(to1))
            {
                break;
            }
        }

        foreach (var s in output.Select(o => root + o))
        {
            Console.WriteLine(s);
        }
    }

但它并不提供所有组合。

【问题讨论】:

  • 感谢您的反对。我能解释一下吗?
  • 我实际上,真的坚持实施这一点,希望能得到一些帮助。我认为这就是 SO 的用途......
  • 那么你尝试了什么,你卡在哪里了?你可以做什么?你有什么问题?你能把“A”变成“B”变成“C”吗?
  • 我说了这么多。我实际上完全不知道如何实现这一点。我可以改变一个字符,但不能生成所有可能的字符。
  • 总是从你作为一个人的方式开始。

标签: c# .net


【解决方案1】:

您要查找的内容称为 base36。因为它是一个用 36 个字母表示的数字。与数字的任何其他表示一样,您将所有表示转换为数字,进行计算,然后将它们转换回显示:

using System;
using System.Linq;

namespace ConsoleApp11
{
    public static class Base36
    {
        private const string Digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        public static string ConvertToBase36(this int value)
        {
            string result = string.Empty;

            while (value > 0)
            {
                result = Digits[value % Digits.Length] + result; 
                value /= Digits.Length;
            }

            return result;
        }

        public static int ConvertFromBase36(this string value)
        {
            return value.Reverse().Select((character, index) => (int)Math.Pow(Digits.Length, index) * Digits.IndexOf(character)).Sum();
        }
    }

    class Program
    {
        static void Main()
        {
            var start = "D3A0";
            var end = "D3AC";

            var startNumber = start.ConvertFromBase36();
            var endNumber = end.ConvertFromBase36();

            while (startNumber < endNumber)
            {
                Console.WriteLine(startNumber.ConvertToBase36());
                startNumber++;
            }

            Console.ReadLine();
        }
    }
}

【讨论】:

  • 这个解决方案看起来也很不错。非常感谢你!我现在将另一个标记为答案,因为我实际上在遵循您的方法时遇到了麻烦,并且将来维护我的代码库的任何人也可能在遵循它时遇到麻烦......对不起。
  • 当我尝试在 VTB_TEST_1VTB_TEST_C 之类的字符串对上使用它时,实际上遇到了溢出错误(我必须在我的数据中处理的实际值)。
  • 那么下划线应该是什么?
  • 他们不应该做任何事情。他们应该被忽略。我可以看到您的方法无法做到这一点,因为它对整个字符串进行编码和解码(当然这是完全正确的)。我的问题是我的客户并没有真正指定边界字符串可以采用什么格式,我现在只是找到了一些带下划线的数据。
【解决方案2】:

这样的事情怎么样:

public static string Next(string current)
{
    if (current.EndsWith("Z"))
        return Next(current.Substring(0, current.Length - 1)) + "0";
    if (current.EndsWith("9"))
        return current.Substring(0, current.Length - 1) + "A";
    return current.Substring(0, current.Length - 1) + (char) (current[current.Length-1] + 1);
}

然后这样称呼它

var value = "A1";
while (value != "CB")
{
    Console.WriteLine(value);
    value = Next(value);
}

【讨论】:

  • 那不只是改变最后一个字符吗?
  • 没有。如果其他字符需要更改,它会递归调用自身。所以在“BZZZ”之后是“C000”。
  • 我将把它标记为答案,因为它很容易理解 :) 谢谢你的帮助!
【解决方案3】:

可能是这样的:

private static string values = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

public static void Main()
{
    string from = "Y5";

    string to = "ZZ";

    var counter = from;
    var output = new List<string>();
    while(counter != to) {
        counter = Increment(counter);
        output.Add(counter);
    }

    Console.WriteLine(string.Join(Environment.NewLine, output));
}

private static string Increment(string counter){
    if(counter.Length < 1) {
        counter = values[0] + counter;
    }

    var lastChar = counter[counter.Length - 1];
    var lastCharIndex = values.IndexOf(lastChar);

    if(lastCharIndex == -1)
    {
        throw new InvalidOperationException("Sequence contains an invalid character: " + lastChar);
    }

    var nextCharIndex = values.IndexOf(lastChar) + 1;

    if(nextCharIndex >= values.Length)
    {
        return Increment(counter.Substring(0, counter.Length - 1)) + values[0];
    }

    return counter.Substring(0, counter.Length - 1) + values[nextCharIndex];
}

应该使用任何值的组合/顺序。

【讨论】:

    【解决方案4】:

    我敲了以下 - 作为第一次努力 - 值被设置为可用的字符选项。这就是人类会这样做的方式。它效率不高,不光彩,但它可以完成工作。

       private static readonly char[] values = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
    
        private static void Main(string[] args)
        {
            Console.Write("Start: ");
            //String start = Console.ReadLine();
            String start = "D98C1";
            Console.Write(" End: ");
            String end = "D9AZ3";
            //String end = Console.ReadLine();
            int i1 = Array.IndexOf(values, start[0]);
            int i2 = Array.IndexOf(values, start[1]);
            int i3 = Array.IndexOf(values, start[2]);
            int i4 = Array.IndexOf(values, start[3]);
            int i5 = Array.IndexOf(values, start[4]);
    
    
            while (String.Format("{0}{1}{2}{3}{4}", values[i1], values[i2], values[i3], values[i4], values[i5]) != end)
            {
                i5++;
                if (i5 == values.Length)
                {
                    i5 = 0;
                    i4++;
                    if (i4 == values.Length)
                    {
                        i4 = 0;
                        i3++;
                        if (i3 == values.Length)
                        {
                            i3 = 0;
                            i2++;
    
                            if (i2 == values.Length)
                            {
                                i2 = 0;
                                i1++;
    
                                if (i1 == values.Length)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
                Console.WriteLine(String.Format("{0}{1}{2}{3}{4}", values[i1], values[i2], values[i3], values[i4], values[i5]));
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-20
      • 2013-05-04
      • 1970-01-01
      • 2012-12-03
      相关资源
      最近更新 更多