创建 1000 个 8 个字符的随机 ID,所有 ID 都是唯一的并显示在文本框中

create 1000, 8-character random ID's, all unique and display in a text box

enter image description here编写一个程序,在单击按钮后在文本框中显示 1000 个 8 字符的随机用户 ID。确保程序验证 none 个 ID 相同。每个用户 ID 应包含字母字符和数字的混合。

到目前为止,我所拥有的可能足以作为一个随机 ID 生成器单独使用,但它不会循环 1000 次以显示在标签中,并且不会检查重复的 ID。

Public Class Form1
    Private Sub btnGenerateRandomID_Click(sender As Object, e As EventArgs) Handles btnGenerateRandomID.Click
        Dim rand As New Random

        Dim char1 As String
        Dim char2 As String
        Dim char3 As String
        Dim char4 As String
        Dim char5 As String
        Dim char6 As String
        Dim char7 As String
        Dim char8 As String


        char1 = ChrW(rand.Next(Asc("A"), Asc("Z") + 1))
        char2 = ChrW(rand.Next(Asc("A"), Asc("Z") + 1))
        char3 = ChrW(rand.Next(Asc("A"), Asc("Z") + 1))
        char4 = ChrW(rand.Next(Asc("A"), Asc("Z") + 1))
        char5 = rand.Next(0, 9)
        char6 = rand.Next(0, 9)
        char7 = rand.Next(0, 9)
        char8 = rand.Next(0, 9)



        lblRandomId.Text = char1 + char2 + char3 + char4 + char5 + char6 + char7 + char8

    End Sub
End Class

谢谢。

编辑:

Public Class Form1 '编写一个程序在文本中显示 1000 个 8 字符的随机用户 ID '单击按钮后的框。确保程序验证 none 个 ID 相同。 '每个用户 ID 应包含字母字符和数字的混合。

Private Sub btnGenerateRandomID_Click(sender As Object, e As EventArgs) Handles btnGenerateRandomID.Click

    Dim strChar As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
    Dim rand As New Random
    Dim strID As String = ""

    For count_ids As Integer = 0 To 999
        For count_chars As Integer = 0 To 7
            strID += strChar(rand.Next(0, 62))
        Next count_chars
        lblRandomId.Text = strID
    Next






End Sub

结束Class

这是实际问题“问。编写一个程序,在单击按钮后在文本框中显示 1000 个 8 字符的随机用户 ID。确保程序验证 none 个 ID 是相同。每个用户 ID 应包含字母字符和数字的混合。

在你的文章中解释你的程序,并附上截图。包括一段关于 Visual Basic 中使用的随机数生成器的段落,并回答问题:随机数生成器应该如何最好地播种?

这将创建名称:

Function RandomName(length As Integer) As String
    Shared rnd As New Random()
    Shared corpus() As Char = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray()
    Return New String(Enumerable.Range(0, length).Select(Function(c) corpus(rnd.Next(corpus.Length))).ToArray())
End Function

Iterator Function GetUniqueNames(length As Integer, count As Integer) As IEnumerable(Of String)
    Dim names As New HashSet(Of String)

    For i As Integer = 0 To count
       Dim name As String = RandomName(length)
       While names.Contains(name)
            'Potential (but unlikely) halting problem
            name = RandomName(length)
        End While
        names.Add(name)
        Yield name
    Next
End Function

Dim uniqueNames = GetUniqueNames(8, 1000)

但是你真的想在一个标签中显示 1000 个吗?

lblRandomId.Text = string.Join(vbCrLf, uniqueNames)

首先,欢迎来到 Whosebug, 据我从你的 post 中了解到你想要生成 1000 个 8 个字符长的唯一 ID 首先我们声明我们的变量

Dim Characters As String = "AZERTYUIOPQSDFGHJKLMWXCVBN0123456789" 'Declare All Characters on one string
Dim IDsList As New List(Of String) With {.Capacity = 1000} 'You can limit the capacity to 1000
Dim Id As String = ""
Dim Rand As New Random

现在我们开始生成 ID 并使用嵌套循环将它们添加到 IDsList

 For i As Integer = 0 To 999 'This is a Zero Based Index so 999 is actually 1000
            For _i As Integer = 0 To 7 'This also means 7 is 8
                Id += Characters(Rand.Next(0, 36))
            Next
            IDsList.Add(Id)
            Id = ""
        Next
            'You can Check for duplicates by adding this piece of code or use the next one instead
            Dim NoDupesIDsList As New List(Of String)
            NoDupesIDsList = IDsList.Distinct.ToList
 For i As Integer = 0 To 999 'This is a Zero Based Index so 999 is actually 1000
            For _i As Integer = 0 To 7 'This also means 7 is 8
                Id += Characters(Rand.Next(0, 36))
            Next
If not IDsList.contains(Id) then
            IDsList.Add(Id)
End if
            Id = ""
        Next

使用带有多行和滚动条的文本框以获得更好的体验 随时通过评论问我任何问题 PS:我测试了我的方法并且它有效,享受吧!

此函数将 return 48 到 122 之间的 ASCII 字符。这将包括一些不是字母或数字的字符,但这会使 ID 更加独特并简化代码。

For 循环构建长度为 8 的 id。然后使用 .Contains 方法检查 id 的唯一性。只有当它不在列表中时,它才被添加到列表中并且计数器递增。

Private Rnd As New Random

Private Function GetListOfIDs() As List(Of String)
    Dim Counter As Integer
    Dim lst As New List(Of String)
    Dim id As String = ""
    Do While Counter < 1000
        id = ""
        For i = 0 To 7
            id &= Chr(Rnd.Next(48, 123))
        Next
        If Not lst.Contains(id) Then
            lst.Add(id)
            Counter += 1
        End If
    Loop
    Return lst
End Function

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim lst = GetListOfIDs()
    TextBox1.Text = String.Join(vbCrLf, lst)
End Sub

编辑

根据 Caius Jard 在评论中的建议,我添加了一个使用 HashSet 的解决方案。同样的想法只有 HashSet 不会接受重复的条目。 .Add 方法 return 是一个布尔值,告诉您添加是否成功。

Private Function GetListOfIDs() As HashSet(Of String)
    Dim hs As New HashSet(Of String)
    Dim id As String = ""
    Do While hs.Count < 1001
        id = ""
        For i = 0 To 7
            id &= Chr(Rnd.Next(48, 123))
        Next
        If hs.Add(id) Then
            Counter += 1
        End If
    Loop
    Return hs
End Function

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim hs = BuildHashSet()
    TextBox1.Text = String.Join(vbCrLf, hs)
End Sub

这种方法可能更有效,因为 HashSet 是为高性能而设计的。对于 1000 个项目,我没有注意到用户界面有任何差异。使用这两种方法立即更新文本框。

让我们谈谈您的代码。

    Dim strChar As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"

这个赋值将在您的循环中起作用,因为字符串实际上是一个字符数组。这就是为什么您可以在字符串中引用索引的原因。

Dim rand As New Random()

.net Random class 为基于系统时间的 Random 提供种子。您很少会想要提供种子。 来自文档 https://docs.microsoft.com/en-us/dotnet/api/system.random?view=netcore-3.1

CONSTRUCTORS

Random() Initializes a new instance of the Random class using a default seed value.

Random(Int32) Initializes a new instance of the Random class, using the specified seed value.

For count_ids As Integer = 0 To 999

For 循环不适用于此问题。我们只想在获得唯一 ID 时增加计数器。上面的 For 循环将在每次迭代时递增。

Do While Counter < 1000
    'Code here
Loop

请注意,在我的代码中,只有当 ID 唯一时,计数器才会递增。

下面的循环应该可以正常工作,但在这段代码之上我们需要将 strID 重置为空字符串。否则我们将得到一个很长的字符串。

For count_chars As Integer = 0 To 7
    strID += strChar(rand.Next(0, 62))
Next count_chars

您不应在循环的每次迭代中更新用户界面(标签)。重绘屏幕是代码中最慢的操作之一。此行将在每次迭代时覆盖标签中的字符串。

lblRandomId.Text = strID

将UI的更新移到两个循环都完成后

您的代码从不检查重复项。

现在让我们修复它。

我们使用 List(Of T) 来累积 ID。 T代表Type;在我们的例子中是 StringList 就像一个数组,只是您不必提前知道会有多少条目。不需要 ReDim Preserve

Dim strID As String = "" 移动到内循环的开头,因此我们将在外循环的每次迭代中得到一个新的 strID

已更改 strID &= strChar(rand.Next(0, 62))&= 而不是 +=。在 VB.net 中,我们使用 & 符号连接字符串,尽管加号也可以。 Random class 的 .Next 方法有一个需要 2 个整数的重载。它包含第一个,不包含第二个,这意味着 (0, 62) 将 return 数字从 0 到 61。长度为 62 的字符串的索引为 0 到 61。

接下来我们使用 List class 的 .Contains 方法检查重复项。此方法的作用正是您所期望的。我们将新 ID 传递给该方法,它 return 是一个 Boolean 告诉该字符串是否已经在列表中。

如果它不在列表中,我们将它添加到列表中并增加计数器。只有在我们成功添加时计数器才会增加。

最后我们使用Stringclass的方法更新了用户界面。 .Join 方法采用分隔符和要加入的列表。 TextBox 必须是多行的并且有滚动条。

我更改了控件的名称,以便可以在我的测试程序中对其进行测试。

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim lst As New List(Of String)
    Dim strChar As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
    Dim rand As New Random()
    Dim counter As Integer
    Do While counter < 1000
        Dim strID As String = ""
        For count_chars = 0 To 7
            strID &= strChar(rand.Next(0, 62))
        Next
        If Not lst.Contains(strID) Then
            lst.Add(strID)
            counter += 1
        End If
    Loop
    TextBox1.Text = String.Join(vbCrLf, lst)
End Sub

编辑

可以在此处找到此方法的官方文档。 https://docs.microsoft.com/en-us/dotnet/api/system.string.join?view=netcore-3.1 我知道这会很难阅读,但请看一下。最终您将能够理解它并会大量使用这些文档。

String.Join(separator, List(Of String))

分隔符是放置在列表中的字符串之间的内容。在我们的例子中,vbCrLf 是换行的 vb 常量。 Cr = Carraiage Return 和 Lf = Line Feed。其他类型的包含字符串的集合也可以使用此方法。

该方法获取列表中的每个字符串并添加分隔符。完成列表后,它 return 是一个长字符串,我们将其显示在 TextBox 中。