【问题标题】:Stopping part of an array being repeated停止重复数组的一部分
【发布时间】:2023-04-02 12:44:01
【问题描述】:
Randomise()
Dim questions(14) as string 
Dim picked questions(4) as string 
Dim rand as new random

Questions(0) = "?"
Questions(1) = "?"
...
Questions(14) = "?" 

For counter = 0 to 4
    Pickedquestions(counter) = questions(rand.next(0,15))
Next 

我有一组问题,我想从这组问题中挑选 5 个问题。然而,我的方法意味着一些挑选的问题与我想避免的相同。有人建议我使用排序算法对数组进行随机排序,然后选择前 5 个。问题是我是初学者,我不明白如何将其合并到我的代码中。任何帮助或其他建议将不胜感激,谢谢。

【问题讨论】:

  • 实际上你想打乱数组并使用其中的前 N ​​个。 Google for Shuffle 和/或 Fisher-Yates,this answer 使用该方法
  • 您也可以将问题复制到一个临时列表(字符串)并从中随机选择它们;随时将它们从临时列表中删除。此外,这里的 Randomize() 对您没有任何作用,因为它与旧的 Rnd() 函数一起使用。您正在使用以当前时间为种子的新 Random() 类;将其从 Dim 更改为 Static

标签: vb.net


【解决方案1】:

这是来自here 的 Jon Skeet 的 Shuffle() 的 VB.Net 版本:

Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Static rnd As New Random

        Dim questions(14) As String
        ' ...

        Dim PickedQuestions = questions.Shuffle(rnd).Take(4).ToArray()
        For i As Integer = 0 To PickedQuestions.Length - 1
            Debug.Print("PickedQuestions(" & i & ") = " & PickedQuestions(i))
        Next
    End Sub

End Class

Module Module1

    ' VB.Net Conversion of Jon Skeet's Shuffle() from: https://stackoverflow.com/a/1287572/2330053
    <System.Runtime.CompilerServices.Extension> _
    Public Iterator Function Shuffle(Of T)(source As IEnumerable(Of T), rng As Random) As IEnumerable(Of T)
        Dim elements As T() = source.ToArray()
        For i As Integer = elements.Length - 1 To 0 Step -1
            Dim swapIndex As Integer = rng.Next(i + 1)
            Yield elements(swapIndex)
            elements(swapIndex) = elements(i)
        Next
    End Function

End Module

好的……这里有一些更“简单”的东西:

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Static rnd As New Random

    Dim questions(14) As String
    For i As Integer = 0 To questions.Count - 1
        questions(i) = "Question " & i
    Next

    Dim tmpQuestions As New List(Of String)(questions)
    Dim PickedQuestions As New List(Of String)
    For i As Integer = 1 To 4
        Dim index As Integer = rnd.Next(tmpQuestions.Count)
        PickedQuestions.Add(tmpQuestions(index))
        tmpQuestions.RemoveAt(index)
    Next

    For i As Integer = 0 To PickedQuestions.Count - 1
        Debug.Print(i & ": " & PickedQuestions(i))
    Next
End Sub

【讨论】:

  • 需要简单一点
【解决方案2】:

打乱questions 数组并获得前四项。只需一点 Linq 就很容易做到这一点:

Imports System
Imports System.Linq

...

Dim questions(14) as string 

...

Dim rnd As New Random
Dim PickedQuestions = questions.OrderBy(Function() rnd.Next).Take(4).ToArray()

Joel 指出,虽然简单且相当直接,但这并不是真正的最佳 方法(但可能足以满足您的目的)。如需更好的排序算法,请参阅John Skeet's answer here

【讨论】:

  • 随机排序。下一个只有作品。对于这个问题,它可能已经足够好了,但在一般情况下,它会在结果中引入偏差。
  • @JoelCoehoorn 是的,但如果我理解的话,只有当两次调用 randome.Next 返回相同的值时才会出现这种偏差。由于范围是 0 - 20 亿,因此从 14 个项目中挑选 4 个项目的偏差将非常小。 OP 似乎他只是在学习,我不想增加他的困惑。尽管如此,为了完整起见,我还是用更多信息更新了我的答案。
  • 我理解这部分。我不明白的是洗牌。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-14
  • 1970-01-01
  • 2012-05-12
  • 1970-01-01
  • 1970-01-01
  • 2021-03-13
相关资源
最近更新 更多