Vb.net все комбинации

У меня есть 6 предметов, которые должны быть объединены,

перечисленные элементы: (это пример)

  • Обезьяна
  • Корова
  • Олень | Маленький олень | Большой олень
  • овец

поэтому «олень» имеет 2 подэлемента.

все эти элементы перечислены в следующем списке:

корова-обезьяна {олень | маленький олень | большой олень} овца

так что вы можете видеть, какой элемент имеет больше элементов.

то, что я хочу, это все эти комбинации:

  • обезьяна корова олень овца

  • обезьяна корова маленький олень овца

  • обезьяна корова большой олень овца

(иногда их больше 6, иногда меньше.

Есть ли кто-нибудь, кто может помочь мне с этим?

РЕДАКТИРОВАТЬ:

Иногда список выглядит примерно так:

  • обезьяна
  • корова
  • Олень | Маленький олень | Большой олень
  • овец
  • мышь | Черная мышь | Белая мышь

(так что больше предметов с подпунктами)


person Ruben    schedule 21.10.2011    source источник
comment
в этом последнем случае вы хотите 9 строк вывода?   -  person Martin    schedule 21.10.2011


Ответы (4)


Вот рекурсивное решение для VB 2010 (вероятно, не очень хорошее с точки зрения производительности, когда есть много комбинаций, но это начало):

Function GetCombinations(items As String()(), Optional index As Integer = 0) As List(Of String())
    Dim combinations As New List(Of String())
    Dim lastIndex = items.Count - 1
    Select Case index
        Case Is < 0, Is > lastIndex
            Throw New ArgumentException("index should be 0 or greater")
        Case lastIndex
            For Each item In items(index)
                combinations.Add({item})
            Next
        Case Else
            Dim nextCombinations = GetCombinations(items, index + 1)
            For Each item In items(index)
                For Each nextCombination In nextCombinations
                    combinations.Add({item}.Concat(nextCombination).ToArray)
                Next
            Next
    End Select
    Return combinations
End Function

Тестовый код:

Dim items = {({"Ape"}), ({"Cow"}), ({"Deer", "Small deer", "Big deer"}), ({"Sheep"}), ({"Mouse", "Black Mouse", "White mouse"})}
For Each combination In GetCombinations(items)
    Console.WriteLine(String.Join(", ", combination))
Next

Тестовые выходы:

Ape, Cow, Deer, Sheep, Mouse
Ape, Cow, Deer, Sheep, Black Mouse
Ape, Cow, Deer, Sheep, White mouse
Ape, Cow, Small deer, Sheep, Mouse
Ape, Cow, Small deer, Sheep, Black Mouse
Ape, Cow, Small deer, Sheep, White mouse
Ape, Cow, Big deer, Sheep, Mouse
Ape, Cow, Big deer, Sheep, Black Mouse
Ape, Cow, Big deer, Sheep, White mouse
person Meta-Knight    schedule 21.10.2011
comment
у меня еще 1 вопрос. я получил список строк, включая элементы, которые я сказал в начале, как я могу преобразовать их в тусклые элементы = (здесь все эти элементы) - person Ruben; 22.10.2011
comment
Для каждой строки в вашем списке вызовите метод Split с символом | в качестве разделителя и преобразовать результат в массив с помощью метода ToArray. - person Meta-Knight; 22.10.2011

Вам понадобится вариант моего решения, которое я представил в ЗДЕСЬ в этом решении для аналогичной проблемы. может быть, достаточно, чтобы получить вас вместе?

Возможно, вам не разрешено видеть ответ, поэтому я скопирую его сюда. Кто-то хотел, чтобы все комбинации 1 и 2 последовательно с длиной 3

   Dim HighestValue As Integer = 2 ' max value
    Dim NrOfValues As Integer = 3 ' nr of values in one result
    Dim Values(NrOfValues) As Integer
    Dim i As Integer
    For i = 0 To NrOfValues - 1
        Values(i) = 1
    Next
    Values(NrOfValues - 1) = 0 ' to generate first as ALL 1
    For i = 1 To HighestValue ^ NrOfValues
        Values(NrOfValues - 1) += 1
        For j As Integer = NrOfValues - 1 To 0 Step -1
            If Values(j) > HighestValue Then
                Values(j) = 1
                Values(j - 1) += 1
            End If
        Next
        Dim Result As String = ""
        For j As Integer = 0 To NrOfValues - 1
            Result = Result & CStr(Values(j))
        Next
        Debug.WriteLine(Result)
    Next

Вам нужно будет поместить значения массива, проиндексированные 1, 2 и т. д., вместо самих чисел, и придумать аналогичную операцию для каждого подсписка.

person Martin    schedule 21.10.2011

Я не могу комментировать подход @Martin, поскольку я не являюсь членом Expert Exchange, но вот как я бы подошел к проблеме.

Вам нужен IEnumerable (из IEnumerable (из T))

Когда у вас есть «Обезьяна», вы должны думать об этом как {Обезьяна}. Это делает ваш список:

{Обезьяна}, {Корова}, {Олень, Маленький олень, Большой олень}, {овца}

Оттуда вы строите свои комбинации, группируя внешний список и перебирая внутренние списки.

т.е. Первый элемент {Ape} имеет только один элемент, поэтому вы можете выполнить итерацию только один раз. То же самое с {Cow}, но третий со всеми оленями будет повторяться более 3 раз.

Этого должно быть достаточно, чтобы вы начали.

person Wesley Long    schedule 21.10.2011

Хотите ввод в виде строк? а рекурсии нет? тогда вот окончательное решение, простая адаптация моего предыдущего примера:

    Dim Lines As New List(Of List(Of String))
    AddItem(Lines, "a ")
    AddItem(Lines, "b ")
    AddItem(Lines, "c1|c2|c3 ")
    AddItem(Lines, "d ")
    AddItem(Lines, "e1|e2")
    AddItem(Lines, "f ") ' etc
    Dim i As Integer
    Dim j As Integer
    Dim ItemnrInLine(Lines.Count - 1) As Integer
    Dim NrCombinations = 1
    For i = 0 To (Lines.Count - 1)
        ItemnrInLine(i) = 0
        NrCombinations *= Lines(i).Count
    Next
    ItemnrInLine(Lines.Count - 1) = -1 ' to get first combination as solution
    For i = 1 To NrCombinations
        ItemnrInLine(Lines.Count - 1) += 1
        For j = Lines.Count - 1 To 0 Step -1
            If ItemnrInLine(j) = Lines(j).Count Then
                ItemnrInLine(j) = 0
                ItemnrInLine(j - 1) += 1
            End If
        Next
        printOut(Lines, ItemnrInLine)
    Next

Sub printOut(ByVal Lines As List(Of List(Of String)), ByVal ItemnrInLine() As Integer)
    Dim Result As String = ""
    For k = 0 To Lines.Count - 1
        Result = Result & Lines(k)(ItemnrInLine(k)).Trim & " "
    Next
    Debug.WriteLine(Result)
End Sub

Sub AddItem(ByVal Lines As List(Of List(Of String)), ByVal inputString As String)
    Dim words() As String = inputString.Split("|"c)
    Dim wordList As New List(Of String)
    For i As Integer = 0 To words.Count - 1
        wordList.Add(words(i))
    Next
    Lines.Add(wordList)
End Sub
person Martin    schedule 22.10.2011