如何使用linq lambda语法查找具有精确长度的子集

时间:2012-11-09 15:47:15

标签: c# linq set

  

可能重复:
  Lists permutations (unknown number)

假设我输入了Range[1, 8]

{1,2,3,4,5,6,7,8}

我希望找到Subsets[%, {2}](所有精确长度为2的子集)

{{1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}, {1, 7}, {1, 8}, {2, 3}, {2, 4}, 
 {2, 5}, {2, 6}, {2, 7}, {2, 8}, {3, 4}, {3, 5}, {3, 6}, {3, 7}, {3, 8}, 
 {4, 5}, {4, 6}, {4, 7}, {4, 8}, {5, 6}, {5, 7}, {5, 8}, {6, 7}, {6, 8}, {7, 8}}

尝试:

var values = Enumerable.Range(1, 8);
var result = from v in values
             from v2 in values.Skip(v)
             select new[] { v, v2 };

3 个答案:

答案 0 :(得分:2)

var query = from a in Enumerable.Range(1, 8)
            from b in Enumerable.Range(a + 1, 8 - a)
            select String.Format("{{{0}, {1}}}", a, b);

foreach (string s in query)
{
    Console.Out.WriteLine(s);
}

答案 1 :(得分:2)

这是一个查找指定大小的输入序列的所有组合的函数:

public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> source, int n)
{
    if (n == 0)
        yield return Enumerable.Empty<T>();


    int count = 1;
    foreach (T item in source)
    {
        foreach (var innerSequence in source.Skip(count).Combinations(n - 1))
        {
            yield return new T[] { item }.Concat(innerSequence);
        }
        count++;
    }
}

因此,在您的情况下,您将其用作:

var result = Enumerable.Range(1, 8).Combinations(2);

答案 2 :(得分:1)

var lst = Enumerable.Range(1, 8);
var result = lst.Join(lst, c => 1, c => 1, (i, j) => new[] { i, j })
        .Where(c => c[0] < c[1]);

在这里,我使用条件1 == 1来获取Enumerable.Range(1, 8)中值的交叉连接,以获得所有可能的组合。

如评论中所述,生成交叉联接的更简单方法是:

var result = lst.SelectMany(_ => lst, (i, j) => new[] { i, j })
        .Where(c => c[0] < c[1]);

但我的眼睛不太可读。

请注意,与其他方法相比,效率稍差,因为它首先获得所有可能的组合,然后减少不需要的组合。然而,简单的单行。