你如何随机遍历一个没有重复的二维数组?
How do you randomly iterate through a 2D array with no duplicates?
您通常会使用两个 for 循环遍历二维数组:
For i = 0 to 5
For j = 0 to 5
Console.Writeline(Arr(i,j))
Next
Next
我需要遍历 2D 数组(具有方形边 - 两边的长度相同,即 5x5 7x7 等),但我需要完全随机地进行,并且不重复相同的元素。
For Each i In iRandArr
For Each j In jRandArr
Console.Writeline(arr(iRandArr(j), jRandArr(i)))
Next
Next
'note: the elements i and j are swapped round above in order to maintain the "column", "row" nomenclature
我已经尝试通过将每一边的长度推入一个列表,随机化它(即取消排序,参见 here),然后以相同的双 for 循环方式迭代来做到这一点。不幸的是,这种方法不是随机迭代,而是通过选择随机“列”并随机迭代“行”来进行半随机迭代。唯一的问题是迭代受列元素的限制,因此不是真正随机的(在编程意义上)。
有没有人有我可以尝试的任何其他可能的选择?
这是我评论中的想法的完整编译实现:
- 构建一组 点 对象,表示二维数组中的一个位置
- 随机化一维点集
- 迭代随机集
请注意,使用自定义点结构的选择是可选的;您可以使用任何您想要的 class/struct 类型,甚至 Tuple
。随机化算法也是如此——使用你想要的任何东西。下面的代码只是问题中 link 中相同逻辑的奇特 LINQ 实现。
Option Explicit On
Option Strict On
Option Infer Off
Option Compare Binary
Imports System
Imports System.Collections.Generic
Imports System.Linq
Module Module1
Sub Main()
'init an array
' this is just for testing purposes;
' presumably the 'real' array comes from somewhere else
Console.WriteLine("Original Array Ordering:")
Const arrayMaxIndex As Integer = 5
Dim arr(arrayMaxIndex, arrayMaxIndex) As Integer
Dim value As Integer = 0
For row As Integer = 0 To arrayMaxIndex
For col As Integer = 0 To arrayMaxIndex
Console.WriteLine($"Row: {row} | Col: {col} | Value: {value}")
arr(row, col) = value
value += 1
Next
Next
'build a 1D list of points that refer to array locations
' this is written separately from initializing the 2D array on purpose,
' since the assumption is that it will be used on an array of unknown origin
Dim pointList As New List(Of Point)
For row As Integer = 0 To arr.GetUpperBound(0)
For col As Integer = 0 To arr.GetUpperBound(1)
pointList.Add(New Point(row, col))
Next
Next
'randomize the 1D list
' choose whatever randomization algorithm you want; this is just one implementation
Dim rnd As New Random
Dim randomizedList As IEnumerable(Of Point) = pointList.OrderBy(Function() rnd.Next())
'step through the randomized 1D list
Console.WriteLine()
Console.WriteLine("Randomized Array Ordering:")
For Each p As Point In randomizedList
Console.WriteLine($"Row: {p.Row} | Col: {p.Col} | Value: {arr(p.Row, p.Col)}")
Next
End Sub
End Module
'use whatever Point type you want
' Didn't want to hard-code to System.Drawing
Friend Structure Point
Public Sub New(row As Integer, col As Integer)
_Row = row
_Col = col
End Sub
Public ReadOnly Property Row As Integer
Public ReadOnly Property Col As Integer
End Structure
示例输出(说明 'randomness' 没有重复):
Original Array Ordering:
Row: 0 | Col: 0 | Value: 0
Row: 0 | Col: 1 | Value: 1
Row: 0 | Col: 2 | Value: 2
Row: 0 | Col: 3 | Value: 3
Row: 0 | Col: 4 | Value: 4
Row: 0 | Col: 5 | Value: 5
Row: 1 | Col: 0 | Value: 6
Row: 1 | Col: 1 | Value: 7
Row: 1 | Col: 2 | Value: 8
Row: 1 | Col: 3 | Value: 9
Row: 1 | Col: 4 | Value: 10
Row: 1 | Col: 5 | Value: 11
Row: 2 | Col: 0 | Value: 12
Row: 2 | Col: 1 | Value: 13
Row: 2 | Col: 2 | Value: 14
Row: 2 | Col: 3 | Value: 15
Row: 2 | Col: 4 | Value: 16
Row: 2 | Col: 5 | Value: 17
Row: 3 | Col: 0 | Value: 18
Row: 3 | Col: 1 | Value: 19
Row: 3 | Col: 2 | Value: 20
Row: 3 | Col: 3 | Value: 21
Row: 3 | Col: 4 | Value: 22
Row: 3 | Col: 5 | Value: 23
Row: 4 | Col: 0 | Value: 24
Row: 4 | Col: 1 | Value: 25
Row: 4 | Col: 2 | Value: 26
Row: 4 | Col: 3 | Value: 27
Row: 4 | Col: 4 | Value: 28
Row: 4 | Col: 5 | Value: 29
Row: 5 | Col: 0 | Value: 30
Row: 5 | Col: 1 | Value: 31
Row: 5 | Col: 2 | Value: 32
Row: 5 | Col: 3 | Value: 33
Row: 5 | Col: 4 | Value: 34
Row: 5 | Col: 5 | Value: 35
Randomized Array Ordering:
Row: 2 | Col: 5 | Value: 17
Row: 3 | Col: 2 | Value: 20
Row: 1 | Col: 0 | Value: 6
Row: 2 | Col: 1 | Value: 13
Row: 4 | Col: 0 | Value: 24
Row: 3 | Col: 5 | Value: 23
Row: 4 | Col: 2 | Value: 26
Row: 5 | Col: 1 | Value: 31
Row: 1 | Col: 5 | Value: 11
Row: 0 | Col: 2 | Value: 2
Row: 4 | Col: 5 | Value: 29
Row: 0 | Col: 5 | Value: 5
Row: 4 | Col: 1 | Value: 25
Row: 3 | Col: 0 | Value: 18
Row: 0 | Col: 4 | Value: 4
Row: 0 | Col: 0 | Value: 0
Row: 1 | Col: 4 | Value: 10
Row: 4 | Col: 3 | Value: 27
Row: 5 | Col: 0 | Value: 30
Row: 2 | Col: 2 | Value: 14
Row: 1 | Col: 1 | Value: 7
Row: 3 | Col: 1 | Value: 19
Row: 2 | Col: 0 | Value: 12
Row: 2 | Col: 4 | Value: 16
Row: 5 | Col: 2 | Value: 32
Row: 0 | Col: 1 | Value: 1
Row: 4 | Col: 4 | Value: 28
Row: 5 | Col: 5 | Value: 35
Row: 1 | Col: 2 | Value: 8
Row: 5 | Col: 4 | Value: 34
Row: 5 | Col: 3 | Value: 33
Row: 1 | Col: 3 | Value: 9
Row: 2 | Col: 3 | Value: 15
Row: 0 | Col: 3 | Value: 3
Row: 3 | Col: 3 | Value: 21
Row: 3 | Col: 4 | Value: 22
P.S。我希望你不要关心这里的性能;这真是一个蛮力实施。
很简单:
Dim Arr As Integer(,) =
{{ 11, 12, 13 }, { 21, 22, 23 }, { 31, 32, 33 }}
Dim random As New Random
Dim indices = _
Enumerable _
.Range(0, 3) _
.SelectMany(Function(i) _
Enumerable _
.Range(0, 3) _
.Select(Function(j) (i, j))) _
.OrderBy(Function(x) random.Next())
For Each x In indices
Console.Writeline(Arr(x.i, x.j))
Next
这只是生成所有可能的索引对,然后随机打乱它们。这样可以确保没有重复。
在这个例子中我得到:
23
32
22
13
33
12
11
31
21
您通常会使用两个 for 循环遍历二维数组:
For i = 0 to 5
For j = 0 to 5
Console.Writeline(Arr(i,j))
Next
Next
我需要遍历 2D 数组(具有方形边 - 两边的长度相同,即 5x5 7x7 等),但我需要完全随机地进行,并且不重复相同的元素。
For Each i In iRandArr
For Each j In jRandArr
Console.Writeline(arr(iRandArr(j), jRandArr(i)))
Next
Next
'note: the elements i and j are swapped round above in order to maintain the "column", "row" nomenclature
我已经尝试通过将每一边的长度推入一个列表,随机化它(即取消排序,参见 here),然后以相同的双 for 循环方式迭代来做到这一点。不幸的是,这种方法不是随机迭代,而是通过选择随机“列”并随机迭代“行”来进行半随机迭代。唯一的问题是迭代受列元素的限制,因此不是真正随机的(在编程意义上)。
有没有人有我可以尝试的任何其他可能的选择?
这是我评论中的想法的完整编译实现:
- 构建一组 点 对象,表示二维数组中的一个位置
- 随机化一维点集
- 迭代随机集
请注意,使用自定义点结构的选择是可选的;您可以使用任何您想要的 class/struct 类型,甚至 Tuple
。随机化算法也是如此——使用你想要的任何东西。下面的代码只是问题中 link 中相同逻辑的奇特 LINQ 实现。
Option Explicit On
Option Strict On
Option Infer Off
Option Compare Binary
Imports System
Imports System.Collections.Generic
Imports System.Linq
Module Module1
Sub Main()
'init an array
' this is just for testing purposes;
' presumably the 'real' array comes from somewhere else
Console.WriteLine("Original Array Ordering:")
Const arrayMaxIndex As Integer = 5
Dim arr(arrayMaxIndex, arrayMaxIndex) As Integer
Dim value As Integer = 0
For row As Integer = 0 To arrayMaxIndex
For col As Integer = 0 To arrayMaxIndex
Console.WriteLine($"Row: {row} | Col: {col} | Value: {value}")
arr(row, col) = value
value += 1
Next
Next
'build a 1D list of points that refer to array locations
' this is written separately from initializing the 2D array on purpose,
' since the assumption is that it will be used on an array of unknown origin
Dim pointList As New List(Of Point)
For row As Integer = 0 To arr.GetUpperBound(0)
For col As Integer = 0 To arr.GetUpperBound(1)
pointList.Add(New Point(row, col))
Next
Next
'randomize the 1D list
' choose whatever randomization algorithm you want; this is just one implementation
Dim rnd As New Random
Dim randomizedList As IEnumerable(Of Point) = pointList.OrderBy(Function() rnd.Next())
'step through the randomized 1D list
Console.WriteLine()
Console.WriteLine("Randomized Array Ordering:")
For Each p As Point In randomizedList
Console.WriteLine($"Row: {p.Row} | Col: {p.Col} | Value: {arr(p.Row, p.Col)}")
Next
End Sub
End Module
'use whatever Point type you want
' Didn't want to hard-code to System.Drawing
Friend Structure Point
Public Sub New(row As Integer, col As Integer)
_Row = row
_Col = col
End Sub
Public ReadOnly Property Row As Integer
Public ReadOnly Property Col As Integer
End Structure
示例输出(说明 'randomness' 没有重复):
Original Array Ordering:
Row: 0 | Col: 0 | Value: 0
Row: 0 | Col: 1 | Value: 1
Row: 0 | Col: 2 | Value: 2
Row: 0 | Col: 3 | Value: 3
Row: 0 | Col: 4 | Value: 4
Row: 0 | Col: 5 | Value: 5
Row: 1 | Col: 0 | Value: 6
Row: 1 | Col: 1 | Value: 7
Row: 1 | Col: 2 | Value: 8
Row: 1 | Col: 3 | Value: 9
Row: 1 | Col: 4 | Value: 10
Row: 1 | Col: 5 | Value: 11
Row: 2 | Col: 0 | Value: 12
Row: 2 | Col: 1 | Value: 13
Row: 2 | Col: 2 | Value: 14
Row: 2 | Col: 3 | Value: 15
Row: 2 | Col: 4 | Value: 16
Row: 2 | Col: 5 | Value: 17
Row: 3 | Col: 0 | Value: 18
Row: 3 | Col: 1 | Value: 19
Row: 3 | Col: 2 | Value: 20
Row: 3 | Col: 3 | Value: 21
Row: 3 | Col: 4 | Value: 22
Row: 3 | Col: 5 | Value: 23
Row: 4 | Col: 0 | Value: 24
Row: 4 | Col: 1 | Value: 25
Row: 4 | Col: 2 | Value: 26
Row: 4 | Col: 3 | Value: 27
Row: 4 | Col: 4 | Value: 28
Row: 4 | Col: 5 | Value: 29
Row: 5 | Col: 0 | Value: 30
Row: 5 | Col: 1 | Value: 31
Row: 5 | Col: 2 | Value: 32
Row: 5 | Col: 3 | Value: 33
Row: 5 | Col: 4 | Value: 34
Row: 5 | Col: 5 | Value: 35
Randomized Array Ordering:
Row: 2 | Col: 5 | Value: 17
Row: 3 | Col: 2 | Value: 20
Row: 1 | Col: 0 | Value: 6
Row: 2 | Col: 1 | Value: 13
Row: 4 | Col: 0 | Value: 24
Row: 3 | Col: 5 | Value: 23
Row: 4 | Col: 2 | Value: 26
Row: 5 | Col: 1 | Value: 31
Row: 1 | Col: 5 | Value: 11
Row: 0 | Col: 2 | Value: 2
Row: 4 | Col: 5 | Value: 29
Row: 0 | Col: 5 | Value: 5
Row: 4 | Col: 1 | Value: 25
Row: 3 | Col: 0 | Value: 18
Row: 0 | Col: 4 | Value: 4
Row: 0 | Col: 0 | Value: 0
Row: 1 | Col: 4 | Value: 10
Row: 4 | Col: 3 | Value: 27
Row: 5 | Col: 0 | Value: 30
Row: 2 | Col: 2 | Value: 14
Row: 1 | Col: 1 | Value: 7
Row: 3 | Col: 1 | Value: 19
Row: 2 | Col: 0 | Value: 12
Row: 2 | Col: 4 | Value: 16
Row: 5 | Col: 2 | Value: 32
Row: 0 | Col: 1 | Value: 1
Row: 4 | Col: 4 | Value: 28
Row: 5 | Col: 5 | Value: 35
Row: 1 | Col: 2 | Value: 8
Row: 5 | Col: 4 | Value: 34
Row: 5 | Col: 3 | Value: 33
Row: 1 | Col: 3 | Value: 9
Row: 2 | Col: 3 | Value: 15
Row: 0 | Col: 3 | Value: 3
Row: 3 | Col: 3 | Value: 21
Row: 3 | Col: 4 | Value: 22
P.S。我希望你不要关心这里的性能;这真是一个蛮力实施。
很简单:
Dim Arr As Integer(,) =
{{ 11, 12, 13 }, { 21, 22, 23 }, { 31, 32, 33 }}
Dim random As New Random
Dim indices = _
Enumerable _
.Range(0, 3) _
.SelectMany(Function(i) _
Enumerable _
.Range(0, 3) _
.Select(Function(j) (i, j))) _
.OrderBy(Function(x) random.Next())
For Each x In indices
Console.Writeline(Arr(x.i, x.j))
Next
这只是生成所有可能的索引对,然后随机打乱它们。这样可以确保没有重复。
在这个例子中我得到:
23
32
22
13
33
12
11
31
21