【问题标题】:Get next string following array of char获取字符数组之后的下一个字符串
【发布时间】:2016-01-27 23:33:16
【问题描述】:

我有一个Arraychars,除了每个字符最多出现一次之外,它是完全随机的。

我还有一个字符串,它只包含数组中存在的字符。我希望这个字符串“向上计数”(如果有道理的话),比如"111" 变成"112",或者"aaa" 变成"aab"

假设charsArray 包含1, 2, and 3。上面的例子有效,但是当字符串是"333"(应该变成"1111")时,我的函数返回一个空的——或者错误的——string

如果我再次调用该函数,提供错误的string,几次后它会返回正确的值 ("1111")。

为什么会这样?

这是我的功能:

Public Function getNextString(ByVal currentStr As String, ByVal pattern() As Char) As String 
    'currentStr is the string which I want to count upwards, pattern() is the array of chars

    Dim nextStr As String = ""

    Dim currentStrArray() As Char = currentStr.ToCharArray
    Dim currenStrPosition As Integer = currentStrArray.Length - 1

    Dim finished As Boolean = False
    Do Until finished = True
        Dim newPosition As Integer = getPositionInArray(currentStrArray(currentStrPosition)) 'this is a custom function, should be self-explaining
        If newPosition = Nothing Then Return Nothing
        newPosition += 1

        Try
            currentStrArray(currenStrPosition) = pattern(newPosition)
            finished = True
        Catch ex As IndexOutOfRangeException
            currentStrArray(currentStrPosition) = pattern(0)
            currentStrPosition -= 1
        End Try

        If currentStrPosition < 0 Then
            nextStr = pattern(0)
            finished = True
        End If
    Loop

    For i As Integer = 0 To currentStrArray.Length - 1
        nextStr = nextStr & currentStrArray(i)
    Next

    Return nextStr
End Function

有什么想法吗?

编辑:

例如,我有数组{"1","2","3"}。我的string 是第一个"111"。我想测试这些strings hashsums。测试该字符串后,我需要下一个string"112"。然后,"113""121""122" 等等。当字符串到达​​"333" 并且该字符串不是我要查找的字符串时,显然它不是只有 3 个字符的字符串(数组可能的所有 3 字符组合都已尝试过)。所以我需要使用 4 个字符重新开始。这就是为什么"333" 应该变成"1111"。 希望这会有所帮助。

编辑#2:

我发现了错误。我错误地重新调整了我的数组,所以最后一个索引是空的。这让我的strings 看起来很奇怪。谢谢大家的工作解决方案,祝你有美好的一天!

【问题讨论】:

  • 为什么333要变成1111?
  • 我想只使用数组中的字符向上计数。如果它只包含 1、2 和 3,它应该只使用这些。就像如果你有所有 10 个数字,99 变成 100。
  • 还是不清楚。您应该显示您的示例数组和字符串。即使是{"1","2","3"},我也不明白为什么333 会变成1111。为什么是 333+1=1111?
  • 我认为它基本上是用随机字符替换数字,所以如果数组是{"a", "b", "c"},你应该把“a”当作0,“b”当作1,“c”当作3,并且以 3 为基数。
  • @Zohar Peled 这些字符可以是任何 Ascii 字符,数组大小只能从 1 char 到 256... 我该怎么做

标签: arrays vb.net string


【解决方案1】:

好吧,我会转换为数字,加 1,然后再转换回字符串。

将字符串转换为数字:

Function ConvertStringToNumber(input As String, pattern As Char()) As Integer
    Dim number As Integer = 0
    Dim charDigits = pattern.ToList()
    Dim numberBase = charDigits.Count
    For i As var = 0 To input.Length - 1
        Dim digit = charDigits.IndexOf(input(input.Length - 1 - i))
        If digit <> -1 Then
            number += digit * CInt(Math.Pow(numberBase, i))
        End If
    Next
    Return number
End Function

将数字转换回字符串:

Function convertNumberToString(number As Integer, pattern As Char()) As String
    Dim charDigits = pattern.ToList()
    Dim numberBase = charDigits.Count
    Dim buffer = New Stack(Of Char)()
    'var j = buffer.Length;
    While number > 0
        buffer.Push(charDigits(number Mod numberBase))
        number = number / numberBase
    End While
    Dim sb = New StringBuilder()
    While buffer.Count > 0
        sb.Append(buffer.Pop())
    End While

    Return sb.ToString()
End Function

现在你有了转换函数,你要做的就是这样:

Function getNextString(ByVal currentStr As String, ByVal pattern() As Char) As String
    Dim number = ConvertStringToNumber(currentStr, pattern)
    number += 1
    Return convertNumberToString(number, pattern)
End Function

【讨论】:

  • 顺便说一句,在您在问题中编写的示例中,“333”应转换为“2111”,因为“1111”基本上是0000。
  • 被接受,因为它简单易用,而且在 vb 中也是如此。请参阅问题中的编辑#2
  • 我用 c# 写了我的答案,并使用在线工具转换为 vb.net。我怀疑自从the c# version works as I intended. 以来转换并不那么完美
  • 你是对的。当然它正在工作。但是当我用我的应用程序进行测试时,它没有,因为我在其他地方犯了一个错误。我删除了我的评论。
  • 顺便说一句,这段代码不能用Option Strict On编译。
【解决方案2】:

如果我理解正确,您想增加特定的基数(数组的长度)。你需要的是一个映射函数,将你的数组字符映射到它们各自的数字,然后从你的基数转换为十进制,递增,转换回来并重新映射。

您能否检查此链接是否有帮助? Quickest way to convert a base 10 number to any base in .NET?

我刚刚用c#写了以下,它似乎可以工作。

    static void Main(string[] args)
    {
        char[] definition = new char[] { 'a', 'b', 'c', 'd', '9', 'x', 'y', 'z', '1', '2', '3'};
        string helperstring = new String(definition);
        int basenumber = definition.Length;
        string mynumberasstring = "333";
        Console.WriteLine(mynumberasstring);
        int correspondingdecimal = 0;
        for (int i = 0; i < mynumberasstring.Length; i++)
        {
            char x = mynumberasstring[mynumberasstring.Length - i - 1];
            int index = helperstring.IndexOf(x);
            int magnitude = 1;
            for (int j = 0; j < i; j++)
                magnitude *= basenumber;
            Console.WriteLine(x + " -> " + index);
            correspondingdecimal += magnitude * index;
        }
        Console.WriteLine(correspondingdecimal + " -> " + ++correspondingdecimal);

        List<int> indicesofnewnumber = new List<int>();

        int newmagnitude = basenumber;
        while(correspondingdecimal > 0)
        {
            int div = correspondingdecimal / basenumber;
            int remainder = correspondingdecimal % basenumber;

            Console.WriteLine("{0} -> {1} ; {2}", correspondingdecimal, div, remainder);

            indicesofnewnumber.Add(remainder);
            correspondingdecimal = div;
        }
        string newnumberasstring = "";
        for (int i = 0; i < indicesofnewnumber.Count; i++)
            newnumberasstring += definition[indicesofnewnumber[indicesofnewnumber.Count - 1 - i]];

        Console.WriteLine(newnumberasstring);
        Console.ReadLine();
    }

【讨论】:

  • 使用我的函数,它使用数组的索引向上计数(这是正确的术语吗?)。比如,{"a","b"} 中的 "a" 是索引 0;我用索引 1 替换它。也许我误解了你......?不确定
  • 我会映射一个 -> 0; b -> 1。所以“ba”会变成“10”,可以转换为2;递增的 3 变为“11”,映射到“bb”。
【解决方案3】:

这是我能想到的将数字转换为任意数字的任意基数的最小代码:

Dim convert As Func(Of Integer, Char(), String) = Nothing
convert = Function (n, cs) _
    If(n \ cs.Length = 0, "", convert(n \ cs.Length, cs)) + cs(n Mod cs.Length)

所以,要将4 转换为二进制,我可以使用convert(4, { "0"c, "1"c }),我会得到100

作为健全性检查,如果我使用 String.Join(", ", Enumerable.Range(0, 32).Select(Function (n) convert(n, { "0"c, "1"c }))) 查看前 32 个(从零开始)二进制数并得到以下信息:

0, 1, 10, 11, 100, 101, 110, 111, 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111, 10000, 10001, 10010, 10011, 101010, 101011, 1, , 11000, 11001, 11010, 11011, 11100, 11101, 11110, 11111

或者从零开始的前 102 个十进制数 String.Join(", ", Enumerable.Range(0, 102).Select(Function (n) convert(n, "0123456789".ToCharArray()))) 我明白了:

0、1、2、3、4、5、6、7、8、9、10、11、12、13、14、15、16、17、18、19、20、21、22、23 , 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48 , 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73 , 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98 , 99, 100, 101

所以我现在可以使用相同类型的代码从数字 { "1"c, "2"c, "3"c } 中获取前 50 个数字,使用 String.Join(", ", Enumerable.Range(0, 50).Select(Function (n) convert(n, "123".ToCharArray()))),我得到了:

1、2、3、21、22、23、31、32、33、211、212、213、221、222、223、231、232、233、311、312、313、321、322、323 , 331, 332, 333, 2111, 2112, 2113, 2121, 2122, 2123, 2131, 2132, 2133, 2211, 2212, 2213, 2221, 2222, 2223, 2231, 2131, 3, 2211, 2, 213, 2, 3, 221, 2, 3, 2 , 2322

这是使用数字{ "1"c, "2"c, "3"c } 的正确“计数”。所以,在这个编号系统中说"333" + 1 = "2111" 是正确的。这与在我们的十进制系统中说999 + 1 = 1000 相同——它显然不是来自999 + 1 = 0000,这意味着"333" + 1 = "1111" 在这个“123”系统中的含义。严格来说我应该写"333" + "2" = "2111"(因为"2"代表1)。

如果您想要所有组合,那么您需要用“零”字符将字符串填充到左侧 - 在本例中为 1。然后这段代码:

String.Join(", ", _
    Enumerable _
        .Range(0, 500) _
        .Select(Function (n) convert(n, "123".ToCharArray()).PadLeft(4, "1"c)) _
        .Where(Function (x) x.Length = 4))

...给出以下 81 个数字:

1111, 1112, 1113, 1121, 1122, 1123, 1131, 1132, 1133, 1211, 1212, 1213, 1221, 1222, 1223, 1231, 1232, 1233, 1311, 1331, 1323, 1321, 1323, , 1331, 1332, 1333, 2111, 2112, 2113, 2121, 2122, 2123, 2131, 2132, 2133, 2211, 2212, 2213, 2221, 2222, 2223, 2231, 2232, 2233, 2311, 2312, 2313, 2321 , 2322, 2323, 2331, 2332, 2333, 3111, 3112, 3113, 3121, 3122, 3123, 3131, 3132, 3133, 3211, 3212, 3213, 3221, 3222, 3223, 3231, 3232, 3233, 3311, 3312 , 3313, 3321, 3322, 3323, 3331, 3332, 3333

...81 是3 x 3 x 3 x 3 = 81 的组合总数。


以下是双向转换的一对函数:

Function Convert(number As Integer, digits As Char()) As String
    Dim r = digits(number Mod digits.Length).ToString()
    If number \ digits.Length <> 0 Then
        r = Convert(number \ digits.Length, digits) + r
    End If
    Return r
End Function

Function Convert(number As String, digits As Char()) As Integer
    Dim r = Array.IndexOf(digits, number(0))
    If number.Substring(1).Length > 0 Then
        r = r * digits.Length + Convert(number.Substring(1), digits)
    End If
    Return r
End Function

【讨论】:

    猜你喜欢
    • 2021-07-18
    • 1970-01-01
    • 2013-05-21
    • 1970-01-01
    • 1970-01-01
    • 2021-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多