Уменьшите вашу путаницу (?), Используя общие версии IEnumerable
и IEnumerator
.
Перечислимая перестановка равна IEnumerable<IEnumerable<T>>
.Таким образом, у вас может быть что-то вроде
IEnumerable<IEnumerable<T>> GetPermutations(IEnumerable<T> sequence)
{
return new Permuter<T>(sequence);
}
и
public class Permuter<T> : IEnumerable<IEnumerable<T>> { ... }
Более того, я видел более одного случая, когда один тип реализовывал и IEnumerable<T>
, и IEnumerator<T>
;его метод GetEnumerator был просто return this;
.
Я думаю, что такой тип должен был бы быть структурой, потому что, если бы это был класс, у вас возникли бы все виды проблем, если бы вы вызывали GetEnumerator () aво второй раз до завершения первого перечисления.
РЕДАКТИРОВАТЬ: использование перестановщика
var permuter = GetPermutations(sequence);
foreach (var permutation in permuter)
{
foreach (var item in permutation)
Console.Write(item + "; ");
Console.WriteLine();
}
Если предположить, что входная последовательность равна {1, 2, 3}, выходной сигнал равен
1; 2; 3;
1; 3; 2;
2; 1; 3;
2; 3; 1;
3; 1; 2;
3; 2; 1;
РЕДАКТИРОВАТЬ:
Вот супер-неэффективная реализация, чтобы проиллюстрировать предложение:
public class Permuter<T> : IEnumerable<IEnumerable<T>>
{
private readonly IEnumerable<T> _sequence;
public Permuter(IEnumerable<T> sequence)
{
_sequence = sequence;
}
public IEnumerator<IEnumerable<T>> GetEnumerator()
{
foreach(var item in _sequence)
{
var remaining = _sequence.Except(Enumerable.Repeat(item, 1));
foreach (var permutation in new Permuter<T>(remaining))
yield return Enumerable.Repeat(item, 1).Concat(permutation);
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}