【问题标题】:How do you randomly iterate through a 2D array with no duplicates?你如何随机迭代一个没有重复的二维数组?
【发布时间】:2022-01-06 23:07:01
【问题描述】:

您通常会使用两个 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),然后以相同的双循环方式迭代。不幸的是,这种方法不是随机迭代,而是通过选择随机“列”并随机迭代“行”来进行半随机迭代。唯一的问题是迭代受列元素的限制,因此不是真正随机的(在编程意义上)。

有没有人可以尝试任何其他可能的选择?

【问题讨论】:

  • 如何通过构建一组覆盖 2D 数组的所有 XY 点,将 1D 点列表随机化,然后迭代随机化的 1D 列表,将 2D 问题分解为 1D 问题?
  • 限制重复也不是真正随机的(在编程意义上)。在实际的随机数中,重复经常发生。因此,通过不允许重复,您根本不会随机迭代
  • @KenWhite - 这是随机选择,没有替换。
  • @SeanSkelly 不幸的是,这会起作用,但是数组的格式不起作用,因为在数组外部迭代时会发生 IndexOutOfBounds 错误。
  • 作为提供的两个答案的附录,您可能需要查找 Fisher-Yates shuffle 作为 Linq order-by-random 的替代方法。

标签: vb.net for-loop multidimensional-array iteration


【解决方案1】:

很简单:

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

【讨论】:

    【解决方案2】:

    这是我评论中该想法的完整编译实现:

    1. 构建一维point对象集,代表二维数组中的位置
    2. 随机化一维点集
    3. 迭代随机集

    请注意,使用自定义 Point 结构的选择是可选的;你可以使用任何你想要的类/结构类型,甚至是Tuple。随机化算法也是如此 - 使用你想要的任何东西。下面的代码只是问题中链接中相同逻辑的一个奇特的 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
    

    示例输出(说明没有重复的“随机性”):

    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
    

    附:我希望你不要关心这里的性能;这确实是一个蛮力实现。

    【讨论】:

    • 这个也很好用,非常感谢。性能并不重要。
    猜你喜欢
    • 1970-01-01
    • 2020-04-01
    • 1970-01-01
    • 2020-01-15
    • 2018-04-16
    • 2018-08-22
    • 2011-11-14
    • 2013-09-30
    • 2012-11-06
    相关资源
    最近更新 更多