1

可能重复:
列出排列(未知数)

可以说我有输入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 };
4

3 回答 3

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);
}
于 2012-11-09T16:08:21.603 回答
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);
于 2012-11-09T16:33:26.140 回答
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]);

但对我来说不太可读。

请注意,与其他方法相比,这种方法的效率要低一些,因为它首先获取所有可能的组合,然后修剪掉不需要的组合。然而,一个简单的单线。

于 2012-11-09T16:28:29.537 回答