他是我的问题。字符串“Case 1 V1:A,B,C ......”。单词“Case 1 V1:” - 是永久性的,A,B,C - 是变量。 意思是我的String可能包含许多元素,通常是三个元素,有时是4-6个元素。我不知道元素的顺序,意味着一次是“案例1 V1:A,B,C”第二次“案例1 V1:B,A,C”。 我想用所有可能的字符串组合制作List。 有没有简单的方法来创建所有组合?
答案 0 :(得分:1)
我碰巧有一种Permute
方法可以满足您的需求。
它输出以下内容,我认为这就是你所要求的:
Case 1 V1: A, B, C
Case 1 V1: A, C, B
Case 1 V1: B, A, C
Case 1 V1: B, C, A
Case 1 V1: C, A, B
Case 1 V1: C, B, A
以下是代码:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Demo
{
internal class Program
{
private void run()
{
string prefix = "Case 1 V1: ";
string[] possibilities = {"A", "B", "C"};
foreach (var permutation in Permute(possibilities))
Console.WriteLine(prefix + string.Join(", ", permutation));
}
public static IEnumerable<IEnumerable<T>> Permute<T>(IEnumerable<T> sequence)
{
return permute(sequence, sequence.Count());
}
private static IEnumerable<IEnumerable<T>> permute<T>(IEnumerable<T> sequence, int count)
{
if (count == 0)
{
yield return new T[0];
}
else
{
int startingElementIndex = 0;
foreach (T startingElement in sequence)
{
IEnumerable<T> remainingItems = allExcept(sequence, startingElementIndex);
foreach (IEnumerable<T> permutationOfRemainder in permute(remainingItems, count - 1))
yield return (new [] { startingElement }).Concat(permutationOfRemainder);
++startingElementIndex;
}
}
}
private static IEnumerable<T> allExcept<T>(IEnumerable<T> input, int indexToSkip)
{
int index = 0;
foreach (T item in input)
{
if (index != indexToSkip)
yield return item;
++index;
}
}
private static void Main()
{
new Program().run();
}
}
}
答案 1 :(得分:1)
怎么样:
public static IEnumerable<IEnumerable<T>> Permutations<T>(IEnumerable<T> items)
{
foreach (var item in items)
{
var head = new T[] { item };
var tail = items.Except(head).ToList();
var subLists = Permutations(tail);
if (subLists.Any())
{
foreach (var subList in subLists)
{
yield return head.Concat(subList);
}
}
else
{
yield return head;
}
}
}
以下
foreach (var p in Permutations(new string[] { "A", "B", "C" }))
{
Console.WriteLine(string.Join(", ", p));
}
产量
A, B, C
A, C, B
B, A, C
B, C, A
C, A, B
C, B, A
请注意,n的顺序很复杂!其中n是列表中的项目数。所以它适用于三个项目,但是一旦你开始进入包含8个或更多项目的列表,就有成千上万的排列。
正如我上面所说,我认为它会好得多,而不是生成所有选项并逐一测试它们,看看实际上是什么,看它是否符合你的期望。检查列表是否具有预期的项目数,然后检查该列表中的某个位置是否每个预期项目至少出现一次。
答案 2 :(得分:1)
您可以使用典型的排名/排名技术进行排列(实际上,在您的情况下,您只需要 unrank ):
public static class Permutations {
public static BigInteger Count(int size) {
if (size < 0)
return 0;
BigInteger result = 1;
for (int i = 2; i <= size; ++i)
result *= i;
return result;
}
public static int[] Unrank(int size, BigInteger rank) {
if (size < 0)
throw new ArgumentOutOfRangeException("size", "size should not be negative.");
else if (rank < 0)
throw new ArgumentOutOfRangeException("rank", "size should not be negative.");
int[] digits = new int[size];
for (int digit = 2; digit <= size; ++digit) {
BigInteger divisor = digit;
digits[size - digit] = (int) (rank % divisor);
if (digit < size)
rank /= divisor;
}
int[] permutation = new int[size];
List<int> usedDigits = new List<int>(size);
for (int i = 0; i < size; ++i)
usedDigits.Add(0);
for (int i = 0; i < size; ++i) {
int v = usedDigits.IndexOf(0, 0);
for (int k = 0; k < digits[i]; ++k)
v = usedDigits.IndexOf(0, v + 1);
permutation[i] = v;
usedDigits[v] = 1;
}
return permutation;
}
}
...
StringBuilder Sb = new StringBuilder();
String data = "Case 1 V1: A, B, C";
String[] items = data.Substring("Case 1 V1:".Length).Trim().Split(',').Select(x => x.Trim()).ToArray();
for (int i = 0; i < (int) Permutations.Count(items.Length); ++i) {
if (Sb.Length > 0)
Sb.AppendLine();
Sb.Append("Case 1 V1: ");
Boolean firstItem = true;
foreach (int j in Permutations.Unrank(items.Length, i)) {
if (!firstItem)
Sb.Append(", ");
firstItem = false;
Sb.Append(items[j]);
}
}
String result = Sb.ToString();
输出
Case 1 V1: A, B, C
Case 1 V1: A, C, B
Case 1 V1: B, A, C
Case 1 V1: B, C, A
Case 1 V1: C, A, B
Case 1 V1: C, B, A