从字符串

时间:2017-06-03 23:35:00

标签: c# string permutation string-length

我在C#中看到很少有字符串变体的实现,但是没有一个对它们的长度有任何限制。不幸的是,我无法修改它们以实现我的目标,例如。

有:

string = "ABCD" and variationLength = 2

生成新字符串:

AB, AC, AD, BA, BC, BD, CA, CB, CD, DA, DB, DC 

我正在寻找这个Python的itertools.permutations实现,但是在C#中。 (https://docs.python.org/3/library/itertools.html#itertools.permutations

C#中有什么类似的吗?如果没有,那么实现它的最简单方法是什么?

Edit_2: 到目前为止,我提出了一个想法,列出给定字符串的所有唯一字符,然后从中获取变体

static void PrintAllKLengthPerm(string str, int k)
{
    int n = str.Length;
    PrintAllKLengthPermRec(str, "", n, k);
}

// The main recursive method to print all possible strings of length k
static void PrintAllKLengthPermRec(string str, String prefix, int n, int k)
{
    // Base case: k is 0, print prefix
    if (k == 0)
    {
        Console.WriteLine(prefix);
        return;
    }

    // One by one add all characters from str and recursively 
    // call for k equals to k-1
    for (int i = 0; i < n; ++i)
    {
        // Next character of input added
        String newPrefix = prefix + str[i];

        // k is decreased, because we have added a new character
        PrintAllKLengthPermRec(str, newPrefix, n, k - 1);
    }
}

static void Main(string[] args)
{
    string str = "ABCD";
    int permLen = 2;

    //get all unique characters in string
    string uniqStr = new String(str.Distinct().ToArray());

    // Print all possible strings of length permLen out of uniqStr characters
    PrintAllKLengthPerm(uniqStr, permLen);      
}

然而,我正在寻找更优化和有效的解决方案

4 个答案:

答案 0 :(得分:1)

List<string> newPermutations = new List<string>();
for(int a = 0; a!=inString.Count; a++)
    for((int b = 0; b!=inString.Count; b++)
        if(noRepetitions && a == b) continue;
        newPermutations.Add(""+inString[a] + inString[b]);

我认为这应该有效;我仍在试图找出一种不仅有2个字母的方法。

编辑:编辑它工作,旧的只是没有工作...大声笑 编辑:感谢@Bloopy,他们帮我发现了我的for循环中的一些错误

答案 1 :(得分:1)

我做了以下递归函数来完成你的任务:

static void Permutations(List<string> output, string str, int n, string curr)
    {
        if(curr.Length == n)
        {
            output.Add(curr);
            return;
        }
        foreach(char c in str)
            if(!curr.Contains(c.ToString()))
                Permutations(output, str, n, curr + c.ToString());
    }

然后你这样称呼它:

string str = "ABCD";
int length = 2;
List<string> perms = new List<string>();
Permutations(perms, str, length, "");
// now the list "perms" will contain the permutations of "str" in length "n"

答案 2 :(得分:1)

这是一种真正的递归排列方法:

public IEnumerable<string> Permutate(string source, int count)
{
    if (source.Length == 1)
    {
        yield return source;
    }
    else if (count == 1)
    {
        for (var n = 0; n < source.Length; n++)
        {
            yield return source.Substring(n, 1);
        }
    }
    else
    {
        for (var n = 0; n < source.Length; n++)
            foreach (var suffix in Permutate(
                source.Substring(0, n)
                    + source.Substring(n + 1, source.Length - n - 1), count -1))
            {
                yield return source.Substring(n, 1) + suffix;
            }
    }
}

可以使用Permutate("ABCD", 2)调用它并返回:

output

答案 3 :(得分:0)

这是使用modulo和division的解决方案。使用字母ABCD有4个可能的长度为2的字符串。将它们从0到4²-1编号并重复将每个数字除以4.将得到的余数用作ABCD字符串上的数组索引。

这样做的好处是可以让你在需要的时候用重复元素(AA,BB,CC,DD)保持字符串 - 只需跳过丢弃步骤。

A(:,1:2) = round( A(:,1:2) )

或者,这是使用LINQ的一个非常简短的解决方案。请注意,如果字符串中存在重复元素,则此方法无法正常工作(除非您要删除对string alphabet = "ABCD"; int length = 2; int[] indexes = new int[length]; char[] item = new char[length]; // loop through all possible strings for the given alphabet and length for (int i = 0; i < Math.Pow(alphabet.Length, length); i++) { int dividend = i; for (int j = length - 1; j >= 0; j--) { indexes[j] = dividend % alphabet.Length; dividend /= alphabet.Length; } // discard any that use the same alphabet element more than once if (indexes.Distinct().Count() < length) continue; for (int k = 0; k < length; k++) { item[k] = alphabet[indexes[k]]; } Console.WriteLine(item); } 的调用并保留AA,BB等)。我需要像上面的方法一样跟踪索引。

Where