【问题标题】:Shuffle an array in vba [duplicate]在vba中随机播放数组[重复]
【发布时间】:2020-04-04 06:10:44
【问题描述】:

我需要在没有重复的情况下对数组中的值进行洗牌,我需要在代码中添加什么以避免重复

Function Resample(data_vector)


   n = UBound(data_vector)
   ReDim shuffled_vector(n)
   For i = 1 To n
      shuffled_vector(i) = data_vector(WorksheetFunction.RandBetween(1, n))
   Next i
End Function

【问题讨论】:

    标签: arrays excel vba shuffle


    【解决方案1】:

    这将使数组随机化:

    Function Resample(data_vector() As Variant) As Variant()
        Dim shuffled_vector() As Variant
        shuffled_vector = data_vector
        Dim i As Long
        For i = UBound(shuffled_vector) To LBound(shuffled_vector) Step -1
            Dim t As Variant
            t = shuffled_vector(i)
            Dim j As Long
            j = Application.RandBetween(LBound(shuffled_vector), UBound(shuffled_vector))
            shuffled_vector(i) = shuffled_vector(j)
            shuffled_vector(j) = t
        Next i
        Resample = shuffled_vector
    End Function
    

    你可以这样调用:

    Sub try()
        Dim x() As Variant
        x = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 0)
    
        x = Resample(x)
    
        MsgBox Join(x, ",")
    End Sub
    

    【讨论】:

    • 您能解释一下为什么(如何)Application.Randbetween,而不是 Worksheetfunction.Randbetween,为什么不是 Rnd?什么是什么?
    • @ScottCraner 我认识我的导师。我只是想通知你,我会删除 cmets
    • @VBasic2008 - Dim 语句未执行;他们在循环中很好。
    • 使用工作表函数对性能很不利,应始终避免。要使此代码快 100 倍以上,请在某处添加此“单行”:Function rndB(min,max): rndB=int((max-min)*rnd())+min: End Function ...然后将 Application.RandBetween 替换为 rndB。通过在循环之前将它们的值粘贴到变量中来避免对UBound/LBound 的如此多的调用,可能会进一步提高性能。
    • 另外,在过程顶部使用 Randomize 初始化随机数生成器很重要(不需要参数)。
    【解决方案2】:

    新数组应该具有相同的维度吗?试试这个:

    Function Resample(data_vector)
       dim upper_bound as Long
       dim lower_bound as Long
       dim dict as Object
       dim i as Long
       dim lRandomNumber As Long
       Set dict = CreateObject("Scripting.Dictionary")
    
       upper_bound = UBound(data_vector)
       lower_bound  = LBound(data_vector)
       ReDim shuffled_vector(upper_bound)
    
       For i = 1 To upper_bound
          lRandomNumber = WorksheetFunction.RandBetween(1, upper_bound)
          If not dict.Exists(Cstr(lRandomNumber)) Then
               shuffled_vector(i) = data_vector(lRandomNumber)
               dict.Add Key:=Cstr(lRandomNumber), Item:=True
          Else
               lRandomNumber = GetNotUsedNumber(dict, lower_bound, upper_bound)
               shuffled_vector(i) = data_vector(lRandomNumber)
               dict.Add Key:=Cstr(lRandomNumber), Item:=True
          End If
       Next i
    End Function
    
    
    Pivate Function GetNotUsedNumber(byref dict as long, byref lower_bound as long, byref upper_bound as long)
    
    dim i as Long
    For i = lower_bound to upper_bound 
    if not dict.exists(Cstr(i)) then
        iResult = i
        Exit For
    end if
    end function
    

    【讨论】:

    • 在另一个答案中查看我的两个comments,因为它们也适用于这里的性能。
    猜你喜欢
    • 2016-07-16
    • 1970-01-01
    • 1970-01-01
    • 2019-04-17
    • 1970-01-01
    • 2014-05-19
    • 1970-01-01
    • 2017-02-20
    • 2021-05-31
    相关资源
    最近更新 更多