Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 随机化列表_Vb.net_List_Random_Shuffle - Fatal编程技术网

Vb.net 随机化列表

Vb.net 随机化列表,vb.net,list,random,shuffle,Vb.net,List,Random,Shuffle,我有这个代码,它工作得很好。输入列表被很好地随机洗牌 但我在理解它为什么起作用方面有点困难 具体来说,oBuffer在这一切中扮演什么角色?为什么要在最后一行: oBuffer(iRandom) = oBuffer(iIndex) 我发现当我对它进行注释时,输出列表中会出现重复项 我已经通过了密码,但我仍然不知所措。这到底是怎么回事 <Extension> Public Iterator Function Randomize(Of T)(Instance As IEnume

我有这个代码,它工作得很好。输入列表被很好地随机洗牌

但我在理解它为什么起作用方面有点困难

具体来说,
oBuffer
在这一切中扮演什么角色?为什么要在最后一行:

oBuffer(iRandom) = oBuffer(iIndex)
我发现当我对它进行注释时,输出列表中会出现重复项

我已经通过了密码,但我仍然不知所措。这到底是怎么回事

  <Extension>
  Public Iterator Function Randomize(Of T)(Instance As IEnumerable(Of T), Rng As Random) As IEnumerable(Of T)
    Dim oBuffer As List(Of T)
    Dim iRandom As Integer
    Dim iIndex As Integer

    Instance.ThrowIfNothing(NameOf(Instance))
    Rng.ThrowIfNothing(NameOf(Rng))

    oBuffer = Instance.ToList

    For iIndex = 0 To oBuffer.Count - 1
      iRandom = Rng.Next(iIndex, oBuffer.Count)
      Yield oBuffer(iRandom)
      oBuffer(iRandom) = oBuffer(iIndex)
    Next
  End Function

公共迭代器函数随机化(Of T)(实例为IEnumerable(Of T),Rng为Random)为IEnumerable(Of T)
Dim OBUFER As列表(共T个)
Dim iRandom作为整数
作为整数的Dim iIndex
Instance.ThrowIfNothing(name of(Instance))
Rng.ThrowIfNothing(名称(Rng))
oBuffer=Instance.ToList
对于iIndex=0的对象,计数为-1
iRandom=Rng.Next(iIndex,oBuffer.Count)
产量OBUFER(伊兰多姆)
oBuffer(iRandom)=oBuffer(iIndex)
下一个
端函数
备选方案(AltRandomize)。请注意,此方法不需要向其传递随机实例

Imports System.Runtime.CompilerServices

Module ModExtensions
    Public PRNG As New Random
    <Extension>
    Public Iterator Function AltRandomize(Of T)(Instance As IEnumerable(Of T)) As IEnumerable(Of T)
        Dim oBuffer As List(Of T)
        'uncomment following
        'Instance.ThrowIfNothing(NameOf(Instance))

        oBuffer = Instance.OrderBy(Function(n) PRNG.Next()).ToList

        For iIndex As Integer = 0 To oBuffer.Count - 1
            Yield oBuffer(iIndex)
        Next
        oBuffer.Clear()
    End Function

    <Extension>
    Public Iterator Function Randomize(Of T)(Instance As IEnumerable(Of T), Rng As Random) As IEnumerable(Of T)
        Dim oBuffer As List(Of T)
        Dim iRandom As Integer
        Dim iIndex As Integer

        'Instance.ThrowIfNothing(NameOf(Instance))
        'Rng.ThrowIfNothing(NameOf(Rng))

        oBuffer = Instance.ToList

        For iIndex = 0 To oBuffer.Count - 1
            iRandom = Rng.Next(iIndex, oBuffer.Count)
            Yield oBuffer(iRandom)
            oBuffer(iRandom) = oBuffer(iIndex)
        Next
    End Function
End Module
导入System.Runtime.CompilerServices
模块ModExtensions
公营公共房屋小组委员会
公共迭代器函数AltRandomize(Of T)(实例为IEnumerable(Of T))为IEnumerable(Of T)
Dim OBUFER As列表(共T个)
'取消以下注释
'Instance.ThrowIfNothing(name of(Instance))
oBuffer=Instance.OrderBy(函数(n)PRNG.Next()).ToList
对于iIndex作为整数=0到oBuffer.Count-1
产量指标(iIndex)
下一个
oBuffer.Clear()
端函数
公共迭代器函数随机化(Of T)(实例为IEnumerable(Of T),Rng为Random)为IEnumerable(Of T)
Dim OBUFER As列表(共T个)
Dim iRandom作为整数
作为整数的Dim iIndex
'Instance.ThrowIfNothing(name of(Instance))
“Rng.ThrowIfNothing(名称(Rng))
oBuffer=Instance.ToList
对于iIndex=0的对象,计数为-1
iRandom=Rng.Next(iIndex,oBuffer.Count)
产量OBUFER(伊兰多姆)
oBuffer(iRandom)=oBuffer(iIndex)
下一个
端函数
端模块

oBuffer
包含原始列表的副本,无论该列表包含什么

该函数在列表中迭代,如下所示:

  • 它从索引0开始,一直到列表的末尾
  • 在的
    的每个循环中,都会生成一个随机数,它基本上是一个优于当前项的索引号
  • 生成
    随机项(将其作为当前正在构建的新列表的下一个元素返回,从索引0开始)
  • 它获取当前项,并将其放在该项先前占用的位置,该项已在列表中,该列表将在函数结束时返回给您

  • 现在你必须通过注释掉最后一行来理解为什么你得到了双倍:它在那里是为了确保当前项目也将被随机分配。这有点像在你面前铲东西,以确保你不会忘记一个,也不会在
    Yield
    ed时再次使用一个。

    这是Fisher-Yates shuffle的一个实现。有一个描述算法的例子。我相信(基于对文章的回顾)为了实现具有线性时间复杂度的算法,就地缓冲区是必要的;如果使用单独的暂存缓冲区,则算法将是O(n²)而不是O(n)。

    oBuffer是原始缓冲区的副本。可能是用来保护原始列表的。我添加了一个具有可选FWIW的答案。@dbasnett该函数将
    IEnumerable
    而不是
    列表作为参数
    oBuffer
    具体化并捕获可枚举的初始内容(可能已延迟)。这是一个很好的解释。请注意,当取消注释循环的最后一行时,
    oBuffer(iRandom)=oBuffer(iIndex)
    oBuffer
    在循环退出时包含重复项。我决定接受。他引用的维基百科文章非常详细地解释了这一点。YW,我感谢你的考虑。我喜欢这个替代品。事实上,我们似乎可以完全不用
    迭代器/Yield
    构造<代码>返回Instance.OrderBy(函数(n)PRNG.Next())
    FYI这是一对重载扩展方法中的第二个。第一个使用一个新的
    Random
    对象调用这个。这一点的存在是为了解决相同序列的问题,如图1所示。“…由于前两个随机对象是紧密连续创建的,因此根据系统时钟使用相同的种子值对它们进行实例化,因此,它们产生相同的随机数序列。”@InteXX-替代方案将只有一个随机实例。如果需要访问应用程序中其他地方的随机对象,只需使用模块中指定的对象。@InteXX迭代器/Yield的使用部分取决于预期用途。如果您总是想要完整的列表(例如,一个纸牌游戏,您总是要处理整个牌组),那么您不需要迭代器。另一方面,如果您通常只需要列表中的一部分,迭代器版本会更有效,因为它只会生成您请求的项目(例如,像扑克这样的纸牌游戏,其中只处理/使用了一部分纸牌)。
    另一种选择将只有一个随机的实例。
    好的,我现在发现了。