C# 基于整数的IEnumerable重复置换

C# 基于整数的IEnumerable重复置换,c#,permutation,ienumerable,C#,Permutation,Ienumerable,我想在C#上做一个IEnumerable置换(带重复)函数。 我已经有了一个使用数组的函数 public IEnumerable<IEnumerable<T>> GetPermsWithReps<T>(IEnumerable<T> items, int count) { foreach (var item in items) { if (count == 1) {

我想在C#上做一个IEnumerable置换(带重复)函数。 我已经有了一个使用数组的函数

public IEnumerable<IEnumerable<T>> GetPermsWithReps<T>(IEnumerable<T> items, int count)
{           
    foreach (var item in items)
    {
        if (count == 1)
        {
            yield return new T[] { item };
        }
        else
        {
            foreach (var result in GetPermsWithReps(items, count - 1))
            {
                yield return new T[] { item }.Concat(result);
            }
        }
    }
}
我应该得到输出

00
01
10
11
我试图通过多种方式修改该函数以实现此目的,但仍然没有成功。。。
有人能帮我吗?

好吧,你可以这样做(假设你想返回字符串):

IEnumerable枚举置换(整数位数,整数长度)
{
变量数据=新字符[长度];
对于(int i=0;i=0;--index)
{
if(++数据[索引]==maxChar)
{
for(int i=索引;i
这样,您可以使用
数字
不同字符获得给定
长度
的任何排列。如果希望基数大于9,则可能应该添加一些映射以使用所需的字符


这段代码只会按词法顺序生成已使用的排列。

因此,您需要了解如何在给定值的情况下,创建一个零和该数字之间所有可能值的序列。您可以查看现有的LINQ方法,看看是否有一个方法可以做到这一点(提示:有一个方法可以做到这一点),或者您可以编写自己的方法;编写这个函数并不十分复杂。@Servy实际上,我可以编写一个函数来转储所有可能的值-但问题是我不想要所有值,我只想分别获取每个记录,并在其中3个记录符合某些条件时停止它-这就是我使用IEnumerable的原因(因为我可以在每个周期后检查记录),并且不想再在那里使用数组作为基本参数(因为这样我就必须首先将所有可能的数字转储到数组中,这是浪费时间和内存的)。你有什么想法吗?创建一个包含
0
1
的序列,然后创建一个包含该序列所有排列的序列本身并不昂贵。你在执行一个复杂度为
n!
的操作;创建一个大小为
n
的输入序列永远不会成功比较中显著。项=可枚举。范围(0,最大值);完成。假设0@Servy0/1转储只是一个例子,我可能需要最多5个数字,最大数字=9。我不确定(没有检查)但是转储所有排列可能需要一些时间,我想避免这种情况,顺便说一下,有了这段代码,我可以执行
枚举排列(222,5).Skip(35000000).take(5)
在我的计算机上大约1秒。因此,如果我对问题下面的注释中给出的参数不做任何其他操作,我每秒迭代大约3500万个值。
00
01
10
11
IEnumerable<string> EnumeratePermutations(int digits, int length)
{
    var data = new char[length];
    for (int i = 0; i < data.Length; ++i)
    {
        data[i] = '0';
    }

    while (true)
    {
        yield return new string(data);

        char maxChar = (char)('0' + digits);

        for (int index = length - 1; index >= 0; --index)
        {
            if (++data[index] == maxChar)
            {
                for (int i = index; i < data.Length; ++i)
                {
                    data[i] = '0';
                }

                if (index == 0)
                {
                    yield break;
                }
            }
            else
            {
                break;
            }
        }
    }
}