Words combinations without repetition

后端 未结 4 691
栀梦
栀梦 2020-12-03 18:58

I have 10 words. How can I get all possible combinations of 5 words (n=10, k=5). The order does not matter.

For example: \"A\",

4条回答
  •  夕颜
    夕颜 (楼主)
    2020-12-03 19:32

    Here's what I put together:

    static class LinqExtensions
    {
        public static IEnumerable> CombinationsWithoutRepetition(
            this IEnumerable items,
            int ofLength)
        {
            return (ofLength == 1) ?
                items.Select(item => new[] { item }) :
                items.SelectMany((item, i) => items.Skip(i + 1)
                                                   .CombinationsWithoutRepetition(ofLength - 1)
                                                   .Select(result => new T[] { item }.Concat(result)));
        }
    
        public static IEnumerable> CombinationsWithoutRepetition(
            this IEnumerable items,
            int ofLength,
            int upToLength)
        {
            return Enumerable.Range(ofLength, Math.Max(0, upToLength - ofLength + 1))
                             .SelectMany(len => items.CombinationsWithoutRepetition(ofLength: len));
        }
    
    }
    

    ...

    foreach (var c in new[] {"a","b","c","d"}.CombinationsWithoutRepetition(ofLength: 2, upToLength: 4))
    {
        Console.WriteLine(string.Join(',', c));
    }
    

    produces:

    a,b
    a,c
    a,d
    b,c
    b,d
    c,d
    a,b,c
    a,b,d
    a,c,d
    b,c,d
    a,b,c,d
    

    Note that this is concise but inefficient and should not be used for large sets or inner loops. Notably, the short arrays are re-created multiple times and could be memoized, and the IEnumerable will be iterated multiple times, which can cause unexpected work if care is not taken.

    Also, if the input contains duplicates then the output will as well. Either use .Distinct().ToArray() first, or use another solution which includes equality checking and, presumably, takes an IEqualityComparer for generality.

提交回复
热议问题