Exemplo n.º 1
0
        private static IEnumerable <IEnumerable <T> > GenerateCombinations <T>(this IEnumerable <T> source, int combinationSize, CombinationsGenerationMode mode)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source), "Source collection is null");
            }

            if (combinationSize == 0)
            {
                return(new[] { new T[] { } });
            }

            IEnumerable <T> sourceList = source as IList <T> ?? source.ToList();

            CombinationsGenerationMode[] distinctModes       = new[] { CombinationsGenerationMode.DistinctOrderSensitive, CombinationsGenerationMode.DistinctOrderInsensitive };
            CombinationsGenerationMode[] orderSensitiveModes = new[] { CombinationsGenerationMode.AllowDuplicatesOrderSensitive, CombinationsGenerationMode.DistinctOrderSensitive };

            if (distinctModes.Contains(mode) && (combinationSize > sourceList.Count()))
            {
                return(new List <IEnumerable <T> >());
            }

            if (sourceList.Count() == 1)
            {
                return(new[] { sourceList });
            }

            var indexedSource = sourceList
                                .Select((x, i) => new
            {
                Item  = x,
                Index = i
            })
                                .ToList();

            return(indexedSource
                   .SelectMany(x => indexedSource
                               .OrderBy(y => x.Index != y.Index)
                               .Skip(distinctModes.Contains(mode) ? 1 : 0)
                               .OrderBy(y => y.Index)
                               .Skip(orderSensitiveModes.Contains(mode) ? 0 : x.Index)
                               .GenerateCombinations(combinationSize - 1, mode)
                               .Select(y => new[] { x }.Concat(y).Select(z => z.Item))
                               ));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Generates all possible subsets of a given size that can be taken from a set. Distinct orderings are counted as distinct sets.
        /// </summary>
        /// <param name="source">A set of items</param>
        /// <param name="combinationSize">The number of items per result set</param>
        /// <param name="mode">The desired mode: whether to use each item from the source set only once, or allow re-use. (Note that Distinct mode requires a <paramref name="combinationSize"/> equal to or greater than the source collection length.)</param>
        /// <returns></returns>
        public static IEnumerable <IEnumerable <T> > Combinations <T>(this IEnumerable <T> source, int combinationSize, CombinationsGenerationMode mode = CombinationsGenerationMode.DistinctOrderInsensitive)
        {
            if (combinationSize < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(combinationSize), "Combination size must be positive and non-zero");
            }

            return(source.GenerateCombinations(combinationSize, mode));
        }