生成两个字母数字字符串范围之间的所有可能组合

时间:2018-05-09 09:56:22

标签: c# .net

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

字符串是字母数字,例如start:D98C1和end:D9AZ3。单个char序列是从0到9的第一个数字,然后是从A到Z的字母。扩展需要生成开始和结束之间的所有可能组合,比如说开始:A1到结束:CA将包含值A1A9AAAZB0B9BABZC0C9CA

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

编辑:

作为一个人,我会从找到不同的开始和结束字符串之间的部分开始。我能做到这一点,这很容易。因此,对于上面的示例,那将是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);
        }
    }

但它没有提供所有组合。

4 个答案:

答案 0 :(得分:5)

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

onclick

enter image description here

答案 1 :(得分:1)

这样的事情怎么样:

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);
}

答案 2 :(得分:0)

也许是这样的:

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];
}

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

答案 3 :(得分:0)

我敲了下面的内容 - 作为第一个努力 - 将值设置为可用的字符选项。这就是人类如何做到这一点。它没有效率,它并不光彩,但它确实起到了作用。

$connectionString = "Data Source=YourServer;Initial Catalog=tempdb;Integrated Security=SSPI;Application Name=PerformanceTestScript";

$guidSetupScript = @"
CREATE TABLE dbo.Example (
  StaticId uniqueidentifier NOT NULL,
  UserId uniqueidentifier NULL,
  UserGroupId uniqueidentifier NULL,
  CompanyId uniqueidentifier NULL,
  CompanyGroupId uniqueidentifier NULL,
  CompanyAccessUnitRole uniqueidentifier NULL,
  PRIMARY KEY CLUSTERED (StaticId)
);
WITH 
     t10 AS (SELECT n FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) t(n))
    ,t1k AS (SELECT 0 AS n FROM t10 AS a CROSS JOIN t10 AS b CROSS JOIN t10 AS c)
    ,t10m AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS num FROM t1k AS a CROSS JOIN t1k AS b CROSS JOIN t1k AS c CROSS JOIN t10 AS d)
INSERT INTO dbo.Example WITH(TABLOCKX) (
      StaticId
    , UserId
    , UserGroupId
    , CompanyId
    , CompanyGroupId
    , CompanyAccessUnitRole
    )
SELECT
      NEWID()
    , NEWID()
    , NEWID()
    , NEWID()
    , NEWID()
    , NEWID()
FROM t10m
WHERE num <= 3000000;
"@

$intSetupScript = @"
CREATE TABLE dbo.Example (
  StaticId int NOT NULL,
  UserId int NULL,
  UserGroupId int NULL,
  CompanyId int NULL,
  CompanyGroupId int NULL,
  CompanyAccessUnitRole int NULL,
  PRIMARY KEY CLUSTERED (StaticId)
);
WITH 
     t10 AS (SELECT n FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) t(n))
    ,t1k AS (SELECT 0 AS n FROM t10 AS a CROSS JOIN t10 AS b CROSS JOIN t10 AS c)
    ,t10m AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS num FROM t1k AS a CROSS JOIN t1k AS b CROSS JOIN t1k AS c CROSS JOIN t10 AS d)
INSERT INTO dbo.Example WITH(TABLOCKX) (
      StaticId
    , UserId
    , UserGroupId
    , CompanyId
    , CompanyGroupId
    , CompanyAccessUnitRole
    )
SELECT
      num
    , num
    , num
    , num
    , num
    , num
FROM t10m
WHERE num <= 3000000;
"@

try
{
    $values = [System.Array]::CreateInstance([System.Object], 6)
    $connection = New-Object System.Data.SqlClient.SqlConnection($connectionString)
    $command = New-Object System.Data.SqlClient.SqlCommand
    $command.CommandTimeout = 0
    $connection.Open()
    $command.Connection = $connection

    #Guid setup
    $command.CommandText = "IF OBJECT_ID(N'dbo.Example') IS NOT NULL DROP TABLE dbo.Example;"
    [void]$command.ExecuteNonQuery()
    $command.CommandText = $guidSetupScript
    [void]$command.ExecuteNonQuery()

    #guid test
    $testSw = [System.Diagnostics.StopWatch]::StartNew()
    Write-Host "Starting Guid test."
    $command.CommandText = "SELECT * FROM dbo.Example;"
    $reader = $command.ExecuteReader()
    while($reader.Read()) {
        $values = $reader.GetValues($values)
    }
    $reader.Close()
    $testSw.Stop()
    Write-Host "Guid test duration was $($testSw.Elapsed.ToString())"

    #int setup
    $command.CommandText = "IF OBJECT_ID(N'dbo.Example') IS NOT NULL DROP TABLE dbo.Example;"
    [void]$command.ExecuteNonQuery()
    $command.CommandText = $intSetupScript
    [void]$command.ExecuteNonQuery()

    #int test
    $testSw = [System.Diagnostics.StopWatch]::StartNew()
    Write-Host "Starting int test."
    $command.CommandText = "SELECT * FROM dbo.Example;"
    $reader = $command.ExecuteReader()
    while($reader.Read()) {
        $values = $reader.GetValues($values)
    }
    $reader.Close()
    $testSw.Stop()
    Write-Host "Int test duration was $($testSw.Elapsed.ToString())"

    $connedtion.Close()

}
catch [Exception]
{
    throw
}