VB .Net Shuffle 2-мерный массив строк - более элегантно - PullRequest
0 голосов
/ 06 мая 2019

Иногда вы просто знаете, что вас застрелят из-за вопроса, но здесь ничего не сказано.

У меня есть двумерный массив строк с именем Вопросы, да, это тест. И БЕЗ изменения исходного типа массива «Вопросы» на более простой, например, «Список структуры», есть ли более элегантный способ изменить порядок вопросов?

Вот что у меня есть:

'1st I create 3 arrays to hold the 3 components of each Question
Dim arrQ((Questions.Length / 4) - 1) As String  'question
Dim arrA((Questions.Length / 4) - 1) As String  'answer
Dim arrM((Questions.Length / 4) - 1) As String  'media name

'2nd I copy the values from question array into individual arrays
Dim z As Integer
For z = 0 To (Questions.Length / 4) - 1
    arrQ(z) = Questions(0, z)
    arrA(z) = Questions(1, z)
    arrM(z) = Questions(2, z)
Next

'create an array to hold our shuffled questions
Dim x As Integer
Dim randarray(total_quizquestions - 1) As Integer

'create a list that we can remove index once they've been added to randarray
Dim list As New ArrayList
For i As Integer = 0 To total_quizquestions - 1
    list.Add(i)
Next i

'add and remove
Dim rand As New Random
Dim index As Integer
For x = 0 To total_quizquestions - 1
    index = rand.Next(0, list.Count)
    randarray(x) = list(index)
    list.RemoveAt(index)
Next

'clear original Questions
ReDim Preserve Questions(3, total_quizquestions - 1)

'add back to questions using randarray random number to get rows from arrQ etc.
Dim f As Integer = 0
For f = 0 To total_quizquestions - 1
    Questions(0, f) = arrQ(randarray(f))
    Questions(1, f) = arrA(randarray(f))
    Questions(2, f) = arrM(randarray(f))
Next f

Привет, мой код работает, но это так ужасно, что мне стыдно! Да, да, у вопросов есть 4 элемента, но меня интересуют только первые 3. Будь добр ...

1 Ответ

2 голосов
/ 06 мая 2019

LINQ плохо работает с двумерными массивами, поэтому ваше требование не менять структуру базового массива исключает множество хороших, элегантных решений.

Тем не менее, вы можете использовать алгоритм тасования Фишера-Йейтса для рандомизации вашего массива на месте.

Этот код основан на ответе, на который я ссылался в предыдущем абзаце (кредит достается Nat Pongjardenlarp). Я адаптировал его к вашему 2D-массиву. Поскольку вы не предоставили MCVE, он полностью не проверен.

Dim rnd As New Random()

For n = total_quizquestions - 1 To 0 Step -1
    Dim j = rnd.Next(0, n + 1)

    ' Swap all three components of the question
    For component = 0 To 2
        Dim temp = Questions(component, n)
        Questions(component, n) = Questions(component, j)
        Questions(component, j) = temp
    Next component
Next n

И, просто для забавы (и потомства), вот обобщенная (и проверенная) версия без "магических чисел", которая перемешивает любой 2D массив:

Private rnd As New Random()

Sub Shuffle2DArray(Of T)(arr As T(,))
    For row = arr.GetUpperBound(1) To arr.GetLowerBound(1) Step -1
        Dim swapRow = rnd.Next(0, row + 1)

        ' Swap all columns of the row
        For column = arr.GetLowerBound(0) To arr.GetUpperBound(0)
            Dim temp = arr(column, row)
            arr(column, row) = arr(column, swapRow)
            arr(column, swapRow) = temp
        Next column
    Next row
End Sub

Очевидно, что вы можете поменять местами Get...Bound(0) и Get...Bound(1), чтобы перемещаться вдоль другой оси двумерного массива.

...