Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.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
Arrays 洗牌一个阵列,使所有物品都不在同一位置_Arrays_Vba_Excel - Fatal编程技术网

Arrays 洗牌一个阵列,使所有物品都不在同一位置

Arrays 洗牌一个阵列,使所有物品都不在同一位置,arrays,vba,excel,Arrays,Vba,Excel,我试图在VBA中随机洗牌字符串数组,同时确保没有项目保留在同一位置 到目前为止,我一直在将所有项目添加到集合中,然后为了将旧数组映射到无序数组,我循环项目。每个项都从集合中移除自身(因此项永远不会转换为自身)。然后,它从剩余的值中选取一个随机项,从集合中移除该项,并将自身添加回集合(以便后面的项可以选取它) 然而,这偶尔意味着最后一个项目永远不会被挑选,因为最后一个项目不能自己挑选,而所有其他项目都可以自己挑选 索引由所有人填充,目标和人都是1索引数组,后者是要洗牌的数组 For i = 1 T

我试图在VBA中随机洗牌字符串数组,同时确保没有项目保留在同一位置

到目前为止,我一直在将所有项目添加到集合中,然后为了将旧数组映射到无序数组,我循环项目。每个项都从集合中移除自身(因此项永远不会转换为自身)。然后,它从剩余的值中选取一个随机项,从集合中移除该项,并将自身添加回集合(以便后面的项可以选取它)

然而,这偶尔意味着最后一个项目永远不会被挑选,因为最后一个项目不能自己挑选,而所有其他项目都可以自己挑选

索引由所有人填充,目标和人都是1索引数组,后者是要洗牌的数组

For i = 1 To UBound(people) ' loop through people
    stillHere = HasKey(indices, "person" & i) 'only remove self from list if not already taken
    If stillHere Then indecies.Remove "person" & i
    randNum = Application.WorksheetFunction.RandBetween(1, indices.Count)
    targets(i) = people(indices(randNum))
    If indices.Count > 1 Then indices.Remove (randNum) 'don't remove the last item of the collection
    If stillHere Then indices.Add i, "person" & i 'only add self back if not already taken
Next i

这是Chip Pearson>


一种适应的洗牌数组,考虑到洗牌数组中的任何项目都不应位于同一位置。它使用与David G提供的相同的初始代码。但是,然后测试碰撞,或者将单个碰撞与另一个随机成员交换,或者如果发现多个碰撞,则将碰撞子集循环一次

我使用字符串数组进行测试

Sub TestShuffle()
    Dim Arr() As String
    Arr = Split("1;2;3;4;5", ";")
    Debug.Print Join(ShuffleArray(Arr), ",")
End Sub

Function ShuffleArray(InArray() As String) As String()
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' ShuffleArray
' This function returns the values of InArray in random order. The original
' InArray is not modified.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

    If UBound(InArray) = 1 Then
        ShuffleArray = InArray
        Exit Function
    End If

    Dim N As Long
    Dim Temp As Variant
    Dim J As Long
    Dim Arr() As String
    Dim Collisions As Collection: Set Collisions = New Collection

    Randomize
    L = UBound(InArray) - LBound(InArray) + 1
    ReDim Arr(LBound(InArray) To UBound(InArray))
    For N = LBound(InArray) To UBound(InArray)
        Arr(N) = InArray(N)
    Next N
    For N = LBound(InArray) To UBound(InArray)
        J = CLng(((UBound(InArray) - N) * Rnd) + N)
        Temp = Arr(N)
        Arr(N) = Arr(J)
        Arr(J) = Temp
    Next N

    For N = LBound(InArray) To UBound(InArray)
        If Arr(N) = InArray(N) Then Collisions.Add N
    Next N

    If Collisions.Count > 1 Then
        Temp = Arr(Collisions.Item(1))
        For N = 1 To Collisions.Count - 1
            Arr(Collisions.Item(N)) = Arr(Collisions.Item(N + 1))
        Next N
        Arr(Collisions.Item(N)) = Temp
    ElseIf Collisions.Count = 1 Then
        J = Collisions.Item(1)
        Do Until J <> Collisions.Item(1)
            J = CLng((UBound(InArray) - LBound(InArray)) * Rnd) + LBound(InArray)
        Loop
        Temp = Arr(Collisions.Item(1))
        Arr(Collisions.Item(1)) = Arr(J)
        Arr(J) = Temp
    End If

    ShuffleArray = Arr

End Function
Sub-TestShuffle()
Dim Arr()作为字符串
Arr=拆分(“1;2;3;4;5”;”)
调试.打印连接(ShufferRay(Arr),“,”)
端接头
函数ShuffleArray(InArray()作为字符串)作为字符串()
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
“沙弗雷
'此函数以随机顺序返回InArray的值。原著
“InArray未被修改。
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
如果UBound(InArray)=1,则
ShuffleArray=InArray
退出功能
如果结束
长
变光温度
Dim J尽可能长
Dim Arr()作为字符串
将碰撞设置为集合:设置碰撞=新集合
随机化
L=UBound(InArray)-LBound(InArray)+1
ReDim Arr(LBound(InArray)至UBound(InArray))
对于N=LBound(InArray)到UBound(InArray)
Arr(N)=InArray(N)
下一个
对于N=LBound(InArray)到UBound(InArray)
J=CLng(((UBound(inaray)-N)*Rnd)+N)
温度=Arr(N)
Arr(N)=Arr(J)
Arr(J)=温度
下一个
对于N=LBound(InArray)到UBound(InArray)
如果Arr(N)=InArray(N),则冲突。添加N
下一个
如果碰撞。计数>1,则
温度=Arr(碰撞。项目(1))
对于N=1的碰撞,计数为-1
Arr(碰撞项目(N))=Arr(碰撞项目(N+1))
下一个
Arr(碰撞项目(N))=温度
ElseIf Collisions.Count=1然后
J=碰撞。项目(1)
直到J碰撞为止。第(1)项
J=CLng((UBound(InArray)-LBound(InArray))*Rnd)+LBound(InArray)
环
温度=Arr(碰撞。项目(1))
第(1)项=第(J)项
Arr(J)=温度
如果结束
ShuffleArray=Arr
端函数

项目的无序排列是这些项目的排列。没有项目保留在其原始位置的排列是混乱的排列。见:

这是一个非常简单的算法。演示代码用于5项:

  • 老鼠
  • 对于输出数组中的每个位置,我们构建一个候选列表,从中进行随机选择。因此,第一个输出的候选项不包括“dog”。第二个输出的候选项不包括“cat”和为第一个输出选择的任何内容

    每个输出的候选列表都会缩小。最后一个输出的候选列表只包含一个项目,所以我们选择它

    最后的输出可能与最后的输入相同。如果发生这种不希望发生的事件,我们只需交换第一个和最后一个输出

    Sub MAIN()
        Dim inpt(1 To 5) As String, Candidate(), j As Long
        Dim i As Long, outpt(), Temp, UTemp As Long
        Dim U As Long, x
    
        inpt(1) = "dog"
        inpt(2) = "cat"
        inpt(3) = "mouse"
        inpt(4) = "bird"
        inpt(5) = "fish"
        U = UBound(inpt)
    
        ReDim outpt(1 To U)
        ReDim Candidate(1 To U)
        For i = 1 To U
            Candidate(i) = inpt(i)
        Next i
    
        For i = 1 To U
            If UBound(Candidate) = 1 Then
                outpt(i) = Candidate(1)
            Else
                outpt(i) = PickValue(Exclude(Candidate, inpt(i)))
                Temp = Exclude(Candidate, outpt(i))
                UTemp = UBound(Temp)
                ReDim Candidate(1 To UTemp)
                For j = 1 To UTemp
                    Candidate(j) = Temp(j)
                Next j
            End If
    
            If inpt(U) = outpt(U) Then
                x = outpt(U)
                outpt(U) = outpt(1)
                outpt(1) = x
            End If
    
    
    
            Cells(i, 2) = inpt(i)
            Cells(i, 4) = outpt(i)
    
        Next i
    
    
    End Sub
    
    Exclude()
    函数输入一个数组和一个要排除的值,并输出一个减少的数组,从中排除:

    Public Function Exclude(ary As Variant, xClude As Variant) As Variant
        Dim c As Collection, i As Long, cCount As Long
        Set c = New Collection
    
        For i = LBound(ary) To UBound(ary)
            If ary(i) = xClude Then
            Else
                c.Add ary(i)
            End If
        Next i
    
        cCount = c.Count
        ReDim bry(1 To c.Count)
        For i = 1 To cCount
            bry(i) = c.Item(i)
        Next i
    
        Exclude = bry
        Set c = Nothing
    End Function
    
    PickValue()
    函数输入一个数组并从该数组中输出一个随机项:

    Public Function PickValue(ary) As Variant
        Dim L As Long, U As Long
    
        L = LBound(ary)
        U = UBound(ary)
    
            With Application.WorksheetFunction
                PickValue = ary(.RandBetween(L, U))
            End With
    End Function
    
    样本输出:

    另一种方法是:

  • 创建所有排列的列表
  • 从该列表中删除非无序排列以形成候选列表
  • 随机挑选候选人

  • 这可能会有所帮助:“没有任何项目保持在同一位置”的概念与“随机分布”的概念不兼容。需要不同的方法。(奇怪的是,就在你做的同一时刻,让其他人去金奇普问不同的问题!)@ashleedawg,这可不酷。Chip有很多很好的代码,我已经对他的代码做了一些修改以使用PowerPoint并发送给他,但我没有收到他的任何答复(这能保证没有任何物品会留在同一个位置吗?这似乎只是把它们放在随机的位置,但可能我没有正确地理解它。)
    Public Function PickValue(ary) As Variant
        Dim L As Long, U As Long
    
        L = LBound(ary)
        U = UBound(ary)
    
            With Application.WorksheetFunction
                PickValue = ary(.RandBetween(L, U))
            End With
    End Function