按顺序生成数字

时间:2011-04-22 13:30:14

标签: c# linq

如果给定startIndex,数字数和最大数,我如何使用LinQ在此序列中生成数字。例如:

Sample Numbers = 1,2,3,4

StartIndex = 1 (i.e it should start from 1)
Sequence number count = 3 
Maximum number = 4 (i.e till 4)

Expected result given the above details :
 1,2,3
 1,3,4
 1,2,4

有没有办法用linQ做到?

3 个答案:

答案 0 :(得分:2)

如果您不需要序列的长度是动态的,那么您可以使用:

var startindex=1;
var maxindex=4;

var data = Enumerable.Range(startindex,maxindex);
var qry = from x in data
          where x == startindex
          from y in data
          where x < y
          from z in data
          where y < z
          select new { x, y, z };
foreach (var tuple in qry) {
    Console.WriteLine("{0} {1} {2}", tuple.x, tuple.y, tuple.z);
}

序列长度硬编码为3,因为有3个可以连接的枚举:x,y,z。

如果您想动态加入任意数量的枚举,那么您可以使用Eric Lippert's Cartesian Product Linq example.

你传递了一组N个项目的k序列,它将返回一组长度为k的所有组合。

现在,您不希望结果中出现重复的元素。 所以,我在Eric的例子中添加了以下内容:

where accseq.All(accitem => accitem < item)

这是最终解决方案(为清晰起见而编辑):

var startindex=1;
var maxindex=7;
var count = 3;

// Make a set of count-1 sequences, whose values range from startindex+1 to maxindex
List<List<int>> sequences = new List<List<int>>();

// We only want permutations starting with startindex.  So, the first input sequence to be joined should only have the value startindex.
List<int> list1 = new List<int>();
list1.Add(startindex);
sequences.Add(list1);

// The rest of the input sequences to be joined should contain the range startindex+1 .. maxindex
for (int i=1; i< count; i++)
{
 sequences.Add(Enumerable.Range(startindex+1,maxindex-startindex).ToList());
}

// Generate the permutations of the input sequences
IEnumerable<IEnumerable<int>> emptyProduct = new[] { Enumerable.Empty<int>() };
var result = sequences.Aggregate( 
    emptyProduct, 
    (accumulator, sequence) =>  
      from accseq in accumulator  
      from item in sequence
      where accseq.All(accitem => accitem < item)
      select accseq.Concat(new[] {item}));                

// Show the result
foreach (var x in result)
{
    Console.WriteLine(x);
}

答案 1 :(得分:0)

尝试此功能。

public static IEnumerable<IEnumerable<T>> Permute<T>(IEnumerable<T> list)
        {
            if (list.Count() == 1)
                return new List<IEnumerable<T>> { list };

            return list.Select((a, i1) => Permute(list.Where((b, i2) => i2 != i1)).Select(b => (new List<T> { a }).Union(b)))
                       .SelectMany(c => c);
        }

//这里范围(startindex,count)

List<int> list1 = Enumerable.Range(1, 3).ToList();

//生成所有排列

var permutationlist = Permute(list1);

enter image description here

答案 2 :(得分:0)

好的,首先让我们清楚地说明问题。我假设你的数字是int,但这是一个大多数不相关的细节,但具体性让思考变得更加白痴

您的序列a_0, a_1, a_2, ..., a_Nint

您有一个满足k的整数1 <= k <= N + 1

您有一个起始索引start >=0和一个结束索引end <= N

您希望所有a_i0, a_i1, a_i2, ..., a_ik长度为k的子序列i0 = startik = end

然后你的算法很简单。您希望生成k - 2的{​​{1}}大小的所有组合。给定这样的组合{ start + 1, ..., end - 1 },对其进行排序,调用生成的有序序列j1, j2, ..., j(k-1)并返回序列i1, i2, ..., i(k-1)

现在你已经知道问题的正式陈述,以及你需要解决的问题,生成所述组合的资源比比皆是。比照Google search : Generating combinations C#Knuth Volume 4A