C # Перестановка массива массивов? - PullRequest
11 голосов
/ 02 апреля 2009

У меня есть ArrayList [] myList, и я пытаюсь создать список всех перестановок значений в массивах.

ПРИМЕР: (все значения являются строками)

myList[0] = { "1", "5", "3", "9" };
myList[1] = { "2", "3" };
myList[2] = { "93" };

Количество myList можно варьировать, поэтому его длина заранее неизвестна.

Я бы хотел составить список всех перестановок, аналогичных приведенным ниже (но с некоторым дополнительным форматированием).

1 2 93
1 3 93
5 2 93
5 3 93
3 2 93
3 3 93
9 2 93
9 3 93

Имеет ли это смысл того, чего я пытаюсь достичь? Я не могу придумать хороший метод для этого (если есть).

Edit:
Я не уверен, что рекурсия помешает моему желанию отформатировать вывод по-своему. Извините, я не упомянул ранее, каково было мое форматирование.

Я хочу закончить построением массива string [] всех комбинаций, следующих за форматом, как показано ниже:

для перестановки "1 2 93"

Я хочу, чтобы вывод был "val0 = 1; val1 = 2; val2 = 93;"

Сейчас я поэкспериментирую с рекурсией. Спасибо, DrJokepu

Ответы [ 12 ]

0 голосов
/ 23 августа 2011

Вот версия, которая использует очень мало кода и является полностью декларативной

    public static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> collection) where T : IComparable
    {
        if (!collection.Any())
        {
            return new List<IEnumerable<T>>() {Enumerable.Empty<T>() };
        }
        var sequence = collection.OrderBy(s => s).ToArray();
        return sequence.SelectMany(s => GetPermutations(sequence.Where(s2 => !s2.Equals(s))).Select(sq => (new T[] {s}).Concat(sq)));
    }
0 голосов
/ 14 декабря 2010

Вот общая рекурсивная функция, которую я написал (и перегрузка, которую удобно вызывать):

Public Shared Function GetCombinationsFromIEnumerables(ByRef chain() As Object, ByRef IEnumerables As IEnumerable(Of IEnumerable(Of Object))) As List(Of Object())
    Dim Combinations As New List(Of Object())
    If IEnumerables.Any Then
        For Each v In IEnumerables.First
            Combinations.AddRange(GetCombinationsFromIEnumerables(chain.Concat(New Object() {v}).ToArray, IEnumerables.Skip(1)).ToArray)
        Next
    Else
        Combinations.Add(chain)
    End If
    Return Combinations
End Function

Public Shared Function GetCombinationsFromIEnumerables(ByVal ParamArray IEnumerables() As IEnumerable(Of Object)) As List(Of Object())
    Return GetCombinationsFromIEnumerables(chain:=New Object() {}, IEnumerables:=IEnumerables.AsEnumerable)
End Function

И эквивалент в C #:

public static List<object[]> GetCombinationsFromIEnumerables(ref object[] chain, ref IEnumerable<IEnumerable<object>> IEnumerables)
{
List<object[]> Combinations = new List<object[]>();
if (IEnumerables.Any) {
    foreach ( v in IEnumerables.First) {
        Combinations.AddRange(GetCombinationsFromIEnumerables(chain.Concat(new object[] { v }).ToArray, IEnumerables.Skip(1)).ToArray);
    }
} else {
    Combinations.Add(chain);
}
return Combinations;
}

public static List<object[]> GetCombinationsFromIEnumerables(params IEnumerable<object>[] IEnumerables)
{
return GetCombinationsFromIEnumerables(chain = new object[], IEnumerables = IEnumerables.AsEnumerable);
}

Простота в использовании:

Dim list1 = New String() {"hello", "bonjour", "hallo", "hola"}
Dim list2 = New String() {"Erwin", "Larry", "Bill"}
Dim list3 = New String() {"!", ".."}
Dim result = MyLib.GetCombinationsFromIEnumerables(list1, list2, list3)
For Each r In result
    Debug.Print(String.Join(" "c, r))
Next

или в C #:

object list1 = new string[] {"hello","bonjour","hallo","hola"};
object list2 = new string[] {"Erwin", "Larry", "Bill"};
object list3 = new string[] {"!",".."};
object result = MyLib.GetCombinationsFromIEnumerables(list1, list2, list3);
foreach (r in result) {
Debug.Print(string.Join(' ', r));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...