C# 从n中获得k个元素的所有组合的算法

C# 从n中获得k个元素的所有组合的算法,c#,algorithm,combinations,C#,Algorithm,Combinations,我有一个列表,我想从2的组合开始对列表中的元素进行一些操作 下面是我的清单: List<string> strArr = new List<string> { "A", "B", "C", "D", "E", "F", "G", "H" }; List strArr=新列表{“A”、“B”、“C”、“D”、“E”、“F”、“G”、“H”}; 如果我们一次选择2个元素,它将生成以下组合:- (A,B)(A,C)(A,D)(A,E)(A,F)(A,G)(A,H)(B,C)

我有一个列表,我想从2的组合开始对列表中的元素进行一些操作

下面是我的清单:

List<string> strArr = new List<string> { "A", "B", "C", "D", "E", "F", "G", "H" };
List strArr=新列表{“A”、“B”、“C”、“D”、“E”、“F”、“G”、“H”};
如果我们一次选择2个元素,它将生成以下组合:- (A,B)(A,C)(A,D)(A,E)(A,F)(A,G)(A,H)(B,C)(B,D) 等等

如果我们一次选择3个元素,它将生成以下组合:- (A,B,C)(A,B,D)(A,B,F)(A,B,G)(A,B,G)(A,C,D)(A,C,G)(A,C,H)(A,C,H)(A,D,E)(A,D,E)(A,D,E)(A,D,G)(A,E,F)(A,F,G,G)(A,F,G,G)(B,C,D)(B,E,E,E)(B,C,E)(B,C,E)(A,F)(A,F,F)(A,F,F,F)(A,E,F,F)(A,F,F,F)(A,C,G,G,F)(A,F,F) 等等

获得这些组合非常容易。我跟着 它给了我精确的输出

但是我不能使用这个代码,因为我有另一个要求,我将继续从列表中删除元素,以防它们满足某些条件,因此组合的数量将继续减少。因此,我不想使用LINQ获得所有的组合,因为在我的情况下,它会影响性能

我想用下面的方法来做:

List<string> strArr = new List<string> { "A", "B", "C", "D", "E", "F", "G", "H" };
// Loop for selecting combination of two elements at time
for (int i = 0; i < strArr.Count; i++)
{
    for (int j = i + 1; j < strArr.Count; j++)
    {
        // Writing on Console
        // Actually do some operation to check whether these two elements in list needs to be removed or not
        Console.Write(strArr[i] + strArr[j]);
        Console.WriteLine();

        // Check whether current combination of 2 elements need to be removed or not
        if (<< condition >>)
        {
            // Remove both the current elements

            // Remove current element of outer loop
            strArr.RemoveAt(i);
            // Remove current element of inner loop
            // Subtracting one as list size is reduced by 1
            strArr.RemoveAt(j - 1);

            //
            i--;
            break;
        }
    }
}

bool isRemoved = false;
// Loop for selecting combination of three elements at time
for (int i = 0; i < strArr.Count; i++)
{
    for (int j = i + 1; j < strArr.Count; j++)
    {
        for (int k = j + 1; k < s.Count; k++)
        {
            // Writing on Console
            // Actually do some operation to check whether these three elements in list needs to be removed or not
            Console.Write(strArr[i] + strArr[j] + strArr[k]);
            Console.WriteLine();

            // Check whether current combination of 3 elements need to be removed or not
            if (<< condition >>)
            {
                // Remove all the three elements

                // Remove current element of outer loop
                strArr.RemoveAt(i);
                // Remove current element of inner loop
                // Subtracting 1 as list size is reduced by 1
                strArr.RemoveAt(j - 1);
                // Subtracting 2 as list size is reduced by 2
                strArr.RemoveAt(k - 2);
                isRemoved = true;
                i--;
                break;
            }

            // If elements are removed then exit from loop with variable j
            if (isRemoved)
            {
                break;
            }
        }
    }
}

// Now make loop for selecting combination of four elements at time
// and keep removing the elements depending upon condition
List strArr=新列表{“A”、“B”、“C”、“D”、“E”、“F”、“G”、“H”};
//一次选择两个元素组合的循环
for(int i=0;i)
{
//删除两个当前元素
//拆下外回路的电流元件
strArr.RemoveAt(一);
//移除内环的电流元件
//列表大小减少1时减去1
strArr.RemoveAt(j-1);
//
我--;
打破
}
}
}
bool isRemoved=false;
//一次选择三个元素组合的循环
for(int i=0;i)
{
//删除所有三个元素
//拆下外回路的电流元件
strArr.RemoveAt(一);
//移除内环的电流元件
//列表大小减少1时减去1
strArr.RemoveAt(j-1);
//列表大小减少2时减去2
strArr.RemoveAt(k-2);
isRemoved=true;
我--;
打破
}
//如果删除了元素,则使用变量j退出循环
如果(已删除)
{
打破
}
}
}
}
//现在进行循环,每次选择四个元素的组合
//并根据情况不断移除元件
删除元素将确保我获得更快的性能,我希望执行此操作,直到结束。我无法思考如何在递归中保持这些循环的深层次。有人能帮我在递归中添加这些无止境的for循环吗

谢谢你花时间为我写解决方案,但这不是我想要的。。。我将简要说明没有代码的要求

  • 假设我有10个元素的列表
  • 我想选择从2到9组开始的所有组合。如果元素总数为10,则可能的组合总数将为1012
  • 现在我想开始评估2组中的所有组合。假设第一组(A,B)。我将根据特定的条件评估该组,如果该组合符合条件,那么我将从10个元素的列表中删除元素(A,B)。所以我将在列表中留下8个元素
  • 现在,剩余8个元素的组合总数将为246。我没有尝试(A,C)(A,D)等组合
  • 但我仍然在评估2组的组合。现在我将挑选2组中的剩余组合。。。下一个组合将是(C,D)(C,E)…假设所有剩余的组合都不满足从列表中删除它们的条件。然后我想开始评估3人一组的组合
  • 第一组3人将是(C、D、E)。。。如果它将通过特定条件,那么我将从列表中删除所有3个元素,只剩下5个元素。现在我想在这5个元素上运行3的组合测试
  • 在那一组4人之后,依此类推
  • 我希望您现在理解这个用例


    有人能帮我实现上述用例吗?

    不确定这是否正是您所需要的,但它可能被认为是一种方法

    namespace ConsoleApplication
    {
        class Program
        {
            static void Main(string[] args)
            {
                List<Tuple<Expression, Expression>>  conditions = new List<Tuple<Expression, Expression>>();
    
                // a complex condition, that the current item contains both "B" and "H"
                Expression<Func<IEnumerable<string>, bool>> expression1 = item => item.Contains("B") && item.Contains("H");
    
                // an expression which is used to exclude the elements from the list
                Expression<Func<string, bool>> expression2 = j => j != "B" && j != "H";
    
                // associate the condition with the exclusion filter
                var condition = new Tuple<Expression, Expression>(expression1, expression2);
    
                conditions.Add(condition);
    
                List<string> strArr = new List<string> { "A", "B", "C", "D", "E", "F", "G", "H" };
    
                IEnumerable<IEnumerable<string>> result = Process(strArr, conditions);
            }
    
            private static IEnumerable<IEnumerable<string>> Process(IEnumerable<string> strArr, List<Tuple<Expression, Expression>> conditions)
            {
                List<IEnumerable<string>> response = new List<IEnumerable<string>>();
                int k = 0;
                for (int i = 1; i <= strArr.Count(); i++)
                {
                    k++;
                    var r = strArr.Combinations(Math.Min(strArr.Count(), k));
                    bool stop=false;
                    foreach (IEnumerable<string> item in r)
                    {
                        if (stop)
                        {
                            break;
                        }
                        foreach (Tuple<Expression, Expression> condition in conditions)
                        {
                            if (Enumerable.Repeat<IEnumerable<string>>(item, 1).Any(Evaluate(condition.Item1) as Func<IEnumerable<string>, bool>))
                            {
                                var initialCount = strArr.Count();
                                strArr = strArr.Where(Evaluate(condition.Item2) as Func<string, bool>);
                                i -= initialCount - strArr.Count();
                                stop = true;
                                break;
                            }
                            else
                            {
                                foreach (var item1 in r)
                                {
                                    response.Add(item1);
                                }
                            }
                        }
    
                    }
                }
                return response;
            }
    
            public static object Evaluate(Expression e)
            {
                if (e.NodeType == ExpressionType.Constant)
                    return ((ConstantExpression)e).Value;
                return Expression.Lambda(e).Compile().DynamicInvoke();
            }
        }
    
        public static class Helper
        {
            public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elements, int k)
            {
                return k == 0 ? new[] { new T[0] } :
                  elements.SelectMany((e, i) =>
                    elements.Skip(i + 1).Combinations(k - 1).Select(c => (new[] { e }).Concat(c))
                    );
            }
        }
    }
    
    命名空间控制台应用程序
    {
    班级计划
    {
    静态void Main(字符串[]参数)
    {
    列表条件=新列表();
    //一个复杂的条件,当前项同时包含“B”和“H”
    表达式expression1=item=>item.Contains(“B”)和&item.Contains(“H”);
    //用于从列表中排除元素的表达式
    表达式2=j=>j!=“B”和&j!=“H”;
    //将条件与排除筛选器关联
    var条件=新元组(表达式1,表达式2);
    条件。添加(条件);
    List strArr=新列表{“A”、“B”、“C”、“D”、“E”、“F”,
    
    public static void PermutateElements<T>(
        IEnumerable<T> elements,
        Predicate<IEnumerable<T>> filterGroup)
    {
        var chooseFrom = new LinkedList<T>(elements);
        var chosen = new List<T>(chooseFrom.Count);
        for (int chooseCount = 2; chooseCount < chooseFrom.Count - 1; chooseCount++)
        {
            Permutate(chooseFrom, chooseCount, filterGroup, chosen, 0);
        }
    }
    
    static bool Permutate<T>(LinkedList<T> chooseFrom, int chooseCount,
        Predicate<IEnumerable<T>> filterPermutation, IList<T> chosen, int skipLast)
    {
        int loopCount = chooseFrom.Count;
        for (int i = 0; i < loopCount; i++)
        {
            var choosingNode = chooseFrom.First;
            chooseFrom.RemoveFirst();
    
            bool removeChosen = false;
            if (i < loopCount - skipLast)
            {
                chosen.Add(choosingNode.Value);
                if (chooseCount == 1)
                    removeChosen = filterPermutation(chosen);
                else
                    removeChosen = Permutate(chooseFrom, chooseCount - 1, filterPermutation, chosen, skipLast + i);
                chosen.RemoveAt(chosen.Count - 1);
            }
            if (!removeChosen)
                chooseFrom.AddLast(choosingNode);
            else if (chosen.Count > 0)
                return true;
        }
        return false;
    }
    
    HashSet<char> vowels = new HashSet<char>(new char[] { 'A', 'E', 'I', 'O', 'U', 'Y' });
    var results = new List<IEnumerable<char>>();
    Predicate<IEnumerable<char>> processGroup = delegate(IEnumerable<char> groupElements)
    {
        int vowelCount = groupElements.Count(x => vowels.Contains(x));
        int consonantCount = groupElements.Count(x => !vowels.Contains(x));
        if (vowelCount < consonantCount && vowelCount > 0)
        {
            results.Add(new List<char>(groupElements));
            return true;
        }
        else
            return false;
    };
    
    var elements = new char[26];
    for (int i = 0; i < elements.Length; i++)
        elements[i] = (char)('A' + i);
    PermutateElements(elements, processGroup);
    
    void r_nCr(const unsigned int &startNum, const unsigned int &bitVal, const unsigned int &testNum) // Should be called with arguments (2^r)-1, 2^(r-1), 2^(n-1)
    {
        unsigned int n = (startNum - bitVal) << 1;
        n += bitVal ? 1 : 0;
    
        for (unsigned int i = log2(testNum) + 1; i > 0; i--) // Prints combination as a series of 1s and 0s
            cout << (n >> (i - 1) & 1);
        cout << endl;
    
        if (!(n & testNum) && n != startNum)
            r_nCr(n, bitVal, testNum);
    
        if (bitVal && bitVal < testNum)
            r_nCr(startNum, bitVal >> 1, testNum);
    }