【问题标题】:create 1000, 8-character random ID's, all unique and display in a text box创建 1000 个 8 个字符的随机 ID,所有 ID 都是唯一的并显示在文本框中
【发布时间】:2020-07-07 21:55:46
【问题描述】:

enter image description here编写一个程序,在单击按钮后在文本框中显示 1000 个 8 个字符的随机用户 ID。确保程序验证没有一个 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

谢谢。

编辑:

公开课表1 '编写一个程序以在文本中显示 1000 个 8 字符的随机用户 ID '单击按钮后的框。确保程序验证没有一个 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

结束类

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

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

【问题讨论】:

  • 这是一项学术作业吗?我问是因为如果我们提供一些基于 LINQ 的令人兴奋的单行解决方案,并且您将其作为对编程 101 任务的响应而提交,您的主管可能很清楚 stackoverflow 已为您完成了作业......
  • 我根据您的编辑发布了第二个答案。看看吧。

标签: vb.net uniqueidentifier do-loops


【解决方案1】:

首先,欢迎来到 StackOverflow, 根据我从您的帖子中了解到的情况,您想要生成 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

使用带有多行和滚动条的文本框以获得更好的体验 随时通过 cmets 向我提问 PS:我测试了我的方法,它的工作,享受它!

【讨论】:

  • 你在哪里检查重复的 ID?
  • 我编辑显示我在哪里。我无法换行来分隔 ID。并且还难以结合 ID 的唯一性。这是我的第一个 vb.net 课程的硬件。
  • 对于单独的行,只需使用 Textbox.text = String.join(vbcrlf,IdsList) 来获得唯一性,请参阅我的编辑我提供了两种检查重复项的方法
【解决方案2】:

此函数将返回 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 在 cmets 中的建议,我添加了一个使用 HashSet 的解决方案。同样的想法只有HashSet 不会接受重复的条目。 .Add 方法返回一个布尔值,告诉您添加是否成功。

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 个项目,我没有注意到用户界面有任何差异。使用这两种方法都会立即更新文本框。

【讨论】:

  • Oof.. 我不确定我是否会使用列表来跟踪重复。除了 Ocomplexity 之外,使用 HashSet 并不断添加它直到其计数达到 1000 会更简单
  • 我编辑显示我在哪里。我无法换行来分隔 ID。并且还难以结合 ID 的唯一性。这是我的第一个 vb.net 课程的硬件。
  • @CaiusJard 我添加了一个 HashSet 解决方案。我有正确的想法吗?
  • 当然.. 或者可以忘记计数器而只询问 hashset 的计数(而 hashSet.Count
  • 多年来我第一次看到 do 循环!
【解决方案3】:

这将创建名称:

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)

【讨论】:

  • 我编辑显示我在哪里。我无法换行来分隔 ID。并且还难以结合 ID 的唯一性。这是我的第一个 vb.net 课程的硬件。
【解决方案4】:

让我们谈谈你的代码。

    Dim strChar As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"

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

Dim rand As New Random()

.net Random 类根据系统时间为 Random 提供种子。您很少愿意提供种子。 来自文档https://docs.microsoft.com/en-us/dotnet/api/system.random?view=netcore-3.1

构造函数

Random() 初始化 Random 类的新实例 使用默认种子值。

Random(Int32) 初始化 Random 类的新实例,使用 指定的种子值。

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 &amp;= strChar(rand.Next(0, 62))&amp;= 而不是 +=。在 VB.net 中,我们使用 & 来连接字符串,尽管加号也可以。 Random 类的 .Next 方法有一个需要 2 个整数的重载。它包括第一个,不包括第二个,这意味着 (0, 62) 将返回从 0 到 61 的数字。长度为 62 的字符串的索引为 0 到 61。

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

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

最后,我们使用String 类的方法更新用户界面。 .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 = 回车和 Lf = 换行。其他类型的包含字符串的集合也可以使用这种方法。

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

【讨论】:

  • 这很好,但是我希望一次创建并显示 1000 个 ID 的列表。这将一次显示一个并重置文本框。
  • @DanLatcovich 不,这将在文本框中列出 1000 个唯一 ID,一个在一行。您一定是错误地复制了代码。我已经测试了这段代码。
  • 我把它复制到了按钮的点击过程中,每次点击它只显示一个。我查看了 multiline 是否正确,并且确实如此。是否还有其他可能影响它的属性,或者它可能是 Visual Studio 2015 的错误?
  • 你需要滚动条。我认为是垂直的。我总是把垂直和水平混淆。我会让文本框足够高,以便您可以看到几行。
  • 我很尴尬,因为我可能对我尝试的许多不同的事情都有正确的答案,但我认为它是在自动调整大小上。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-19
  • 2011-02-20
  • 1970-01-01
  • 1970-01-01
  • 2012-10-14
  • 1970-01-01
  • 2020-10-24
相关资源
最近更新 更多