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