C# 使用相同字母的排列

C# 使用相同字母的排列,c#,algorithm,permutation,C#,Algorithm,Permutation,我目前正在从事一个项目,需要从给定的字符集生成所有可能的排列。我目前正在使用此代码: public static IEnumerable<string> AllPermutations(this IEnumerable<char> s) { return s.SelectMany(x => { var index = Array.IndexOf(s.ToArray(), x); return s.Where((y, i

我目前正在从事一个项目,需要从给定的字符集生成所有可能的排列。我目前正在使用此代码:

public static IEnumerable<string> AllPermutations(this IEnumerable<char> s)
{
    return s.SelectMany(x =>
    {
        var index = Array.IndexOf(s.ToArray(), x);
        return s.Where((y, i) => i != index).AllPermutations().Select(y => new string(new[] { x }.Concat(y).ToArray())).Union(new[] { new string(new[] { x }) });
    }).Distinct();
}
公共静态IEnumerable所有置换(此IEnumerable s)
{
返回s.SelectMany(x=>
{
var index=Array.IndexOf(s.ToArray(),x);
返回s.Where((y,i)=>i!=index).AllPermutations().Select(y=>newstring(new[]{x}.Concat(y).ToArray()).Union(new[]{newstring(new[]{x})});
}).Distinct();
}
从答案来看

我的问题是,它不会生成多次使用同一个字母的置换

例如,如果我使用
abcde
作为输入,我需要它生成像
aaaaa
dcc
等组合

我对LINQ没有足够的经验来理解代码在哪里阻止重复的字母。非常感谢您的帮助。

这可能会奏效,但我相信可以更有效地完成(从PeskyGnat获得计数提示):

静态IEnumerable GetVariations(字符串s)
{
int[]索引=新的int[s.Length];
StringBuilder sb=新的StringBuilder();
while(递增索引(索引,s.Length))
{
(某人清楚地);
for(int i=0;i限制)
{
指数[i]=1;
}
其他的
{
返回true;
}
}
返回false;
}
编辑:根据罗林斯的建议更改为使用收益率回报。如果您不需要保留所有结果,并且可以在所有结果生成之前就开始使用这些结果,那么内存使用情况会更好。

这可能会起作用,但我相信可以更有效地完成(从PeskyGnat获得计数提示):

静态IEnumerable GetVariations(字符串s)
{
int[]索引=新的int[s.Length];
StringBuilder sb=新的StringBuilder();
while(递增索引(索引,s.Length))
{
(某人清楚地);
for(int i=0;i限制)
{
指数[i]=1;
}
其他的
{
返回true;
}
}
返回false;
}

编辑:根据罗林斯的建议更改为使用收益率回报。如果您不需要保留所有结果,并且可以在所有结果生成之前就开始使用它们,那么内存使用情况会更好。

我很惊讶这能奏效。它基本上是这样的:“从字符中列出一个字符串列表。然后对从列表中提取的每个字符串,再次添加每个字符,并将结果字符串添加到列表中。重复操作,直到获得正确的长度。”

公共静态IEnumerable构建字符串(此IEnumerable字母表)
{
var strings=alphabet.Select(c=>c.ToString());
对于(int i=1;ialphabet.Select(c=>s+c.ToString()));
}
返回字符串;
}

我很惊讶这能奏效。它基本上是这样的:“从字符中列出一个字符串列表。然后对从列表中提取的每个字符串,再次添加每个字符,并将结果字符串添加到列表中。重复操作,直到获得正确的长度。”

公共静态IEnumerable构建字符串(此IEnumerable字母表)
{
var strings=alphabet.Select(c=>c.ToString());
对于(int i=1;ialphabet.Select(c=>s+c.ToString()));
}
返回字符串;
}

一个有趣的例子,通过不动点操作符仅使用递归lambda(对于SelectMany,thx@Rawling)

//定点运算符
公共静态函数修复(函数f)
{
返回t=>f(Fix(f))(t);
}
然后

var chars = new[] {'a','b','c','d','e'}.Select(c=>c.ToString()) ;

var result = Fix<int,IEnumerable<string>>(
    f => 
      x => 
       x == 1
         ? chars
         : chars.Union(f(x - 1).SelectMany(s => chars.Select(c => s + c))))(chars.Count());
var chars=new[]{'a','b','c','d','e'}。选择(c=>c.ToString());
var结果=修复(
f=>
x=>
x==1
?chars
:chars.Union(f(x-1).SelectMany(s=>chars.Select(c=>s+c)))(chars.Count());

一个有趣的例子,通过不动点操作符仅使用递归lambda(对于SelectMany,thx@Rawling)

//定点运算符
公共静态函数修复(函数f)
{
返回t=>f(Fix(f))(t);
}
然后

var chars = new[] {'a','b','c','d','e'}.Select(c=>c.ToString()) ;

var result = Fix<int,IEnumerable<string>>(
    f => 
      x => 
       x == 1
         ? chars
         : chars.Union(f(x - 1).SelectMany(s => chars.Select(c => s + c))))(chars.Count());
var chars=new[]{'a','b','c','d','e'}。选择(c=>c.ToString());
var结果=修复(
f=>
x=>
x==1
?chars
:chars.Union(f(x-1).SelectMany(s=>chars.Select(c=>s+c)))(chars.Count());

在LINQ中这样做有什么原因吗?我没有写这篇文章,所以我只是在寻找真正起作用的代码。“aaaaa”不是“abcde”的变体。如果您的项目需要排列,但不包括“aaaaa”,如果您包括“aaaaa”,则不要将其称为排列(或组合)。阅读你的问题的人,包括你自己,都会感到困惑。也许你需要的是重复的变化。我还需要任何更短的版本,从1个字符到字符串长度,以任何顺序使用所有输入字母。在LINQ中这样做有什么原因吗?我没有写这个,所以只是看看
// Fix point operator   
public static Func<T, TResult> Fix<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> f)
    {
        return t => f(Fix<T, TResult>(f))(t);
    }
var chars = new[] {'a','b','c','d','e'}.Select(c=>c.ToString()) ;

var result = Fix<int,IEnumerable<string>>(
    f => 
      x => 
       x == 1
         ? chars
         : chars.Union(f(x - 1).SelectMany(s => chars.Select(c => s + c))))(chars.Count());