n列表的笛卡尔积

我有一个特定类型的列表,我的要求是从它们创建笛卡尔积。 我该怎么做。

我可以找出静态数量的列表,但动态的列表数令我惊讶。 感谢您在这方面的帮助。

我有一个ideea:使用表达式树动态生成满足您需求的代码:

这是一个完整的解决方案:

using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text; namespace testProjectExpressions { class Program { static void Main(string[] args) { List lst1 = new List() { 1, 2, 3 }; List lst2 = new List() { 4, 5, 6 }; List lst3 = new List() { 7, 8 }; var fnc = CartesianProduct(3); var res = fnc(new[] {lst1, lst2, lst3 }); foreach (var product in res) { for (int index = 0; index < product.Length; index++) { var productVar = product[index]; if (index < product.Length - 1) Console.Write(productVar + ","); else { Console.WriteLine(productVar); } } } Console.ReadKey(); } private static Func[], List> CartesianProduct(int howMany) { var inputArrayOfLists = Expression.Parameter(typeof (List[]), "inputArgument"); ParameterExpression[] loopVariables = new ParameterExpression[howMany]; for (int index = 0; index < howMany; index++) if (loopVariables[index] == null) loopVariables[index] = Expression.Variable(typeof (T)); List finalStatements = new List(); // emit the create new object var resultExpression = Expression.Variable(typeof (List), "result"); var assignExpression = Expression.Assign(resultExpression, Expression.New(typeof (List))); finalStatements.Add(assignExpression); // the "Add" method MethodInfo addMethod = typeof (List).GetMethod("Add", BindingFlags.Instance | BindingFlags.Public); var EnumerableType = typeof(IEnumerable); MethodInfo GetEnumeratorMethod = EnumerableType.GetMethod("GetEnumerator"); var moveNextMethod = typeof(IEnumerator).GetMethod("MoveNext"); Expression recursiveExpression = null; for (int index = 0; index < howMany; index++) { var variable = loopVariables[index]; var indexAccess = Expression.ArrayIndex(inputArrayOfLists, Expression.Constant(index)); var currentListExpression = indexAccess; if (recursiveExpression == null) { var arrayVariable = Expression.Variable(typeof (T[]), "myArray"); List initExpressions = new List(); List statements = new List(); var assign = Expression.Assign(arrayVariable, Expression.NewArrayInit(typeof (T), loopVariables)); statements.Add(assign); Expression callAddExpression = Expression.Call(resultExpression, addMethod, arrayVariable); statements.Add(callAddExpression); recursiveExpression = Expression.Block(new[] {arrayVariable}, statements); } recursiveExpression = ForEachExpression(typeof(IEnumerator), GetEnumeratorMethod, moveNextMethod, currentListExpression, variable, recursiveExpression); } finalStatements.Add(recursiveExpression); finalStatements.Add(resultExpression); List blockParameters = new List(loopVariables); blockParameters.Add(resultExpression); Expression block = Expression.Block(blockParameters, finalStatements); var compiled = Expression.Lambda(block, inputArrayOfLists).Compile() as Func[], List>; return compiled; } // compiles a foreach expression on the given collection! public static Expression ForEachExpression( Type enumeratorType, MethodInfo getEnumeratorMethod, MethodInfo moveNextMethod, Expression collection, ParameterExpression loopVariable, Expression loopContent) { var breakLabel = Expression.Label("STOP"); var enumeratorVar = Expression.Variable(enumeratorType, "collectionEnumerator"); var loop = Expression.Block(new[] { enumeratorVar }, Expression.Assign(enumeratorVar, Expression.Call(collection, getEnumeratorMethod)), // var enumerator = collection.GetEnumerator (); Expression.Loop( Expression.IfThenElse( Expression.Equal(Expression.Call(enumeratorVar, moveNextMethod), Expression.Constant(true)), // daca move_next e true Expression.Block(new[] { loopVariable }, Expression.Assign(loopVariable, Expression.Property(enumeratorVar, "Current")), // loopVariable = enumeratorVar.Current loopContent // do some stuff with that entity ), Expression.Break(breakLabel) // jmp to break ), breakLabel) // break ); return loop; } } }