如何使用LINQ对未知数量的字符串数组执行交叉连接?
在LINQ中对n个字符串数组执行交叉连接(笛卡尔积)
当然可以!当你需要对n个字符串数组执行交叉连接(也就是笛卡尔积)时,LINQ完全能实现这个需求——核心是用迭代累积或者递归的方式动态构建结果,而不用写死固定数量的Join或SelectMany。
方法一:使用迭代+SelectMany累积构建
最直观的方式是用循环配合SelectMany,从一个初始的“空结果”开始,逐个和后续的数组做交叉连接,逐步组合出最终的笛卡尔积。
以下是实现代码:
public static IEnumerable<string[]> CrossJoin(params string[][] arrays) { // 初始值:一个仅包含空数组的集合,作为笛卡尔积的起始基准 IEnumerable<string[]> result = new[] { Array.Empty<string>() }; foreach (var array in arrays) { // 跳过空数组,避免直接得到空结果(可选,根据你的业务需求调整) if (!array.Any()) return Enumerable.Empty<string[]>(); // 将当前累积的结果与下一个数组的每个元素交叉组合 result = result.SelectMany(prevCombination => array, (prevItems, currentItem) => prevItems.Concat(new[] { currentItem }).ToArray()); } return result; }
代码说明:
- 初始的
result是一个只有空数组的集合,这样第一次循环时,会把空数组和第一个数组的每个元素组合,得到第一个数组的所有元素(每个元素作为单独的数组)。 - 后续每次循环,都会把之前的所有组合结果,和当前数组的每个元素重新组合,最终得到n个数组的完整笛卡尔积。
- 额外加了空数组判断,如果输入中存在空数组,直接返回空结果(符合笛卡尔积的数学定义:只要有一个集合为空,结果就为空)。
使用示例:
var group1 = new[] { "a", "b" }; var group2 = new[] { "1", "2" }; var group3 = new[] { "x", "y" }; var group4 = new[] { "!", "@" }; // 传入任意数量的数组 var crossJoinedResult = CrossJoin(group1, group2, group3, group4); // 输出的每个元素都是一个组合数组,比如 ["a","1","x","!"]、["a","1","x","@"] 等等 foreach (var combination in crossJoinedResult) { Console.WriteLine(string.Join(", ", combination)); }
方法二:递归实现
如果你更喜欢递归的写法,也可以通过递归拆分问题:每次处理第一个数组,然后递归处理剩下的数组,再把两者的结果组合起来。
代码示例:
public static IEnumerable<string[]> CrossJoinRecursive(IEnumerable<string[]> arrays) { var arrayList = arrays.ToList(); // 递归终止条件:没有剩余数组时,返回包含空数组的集合 if (arrayList.Count == 0) { yield return Array.Empty<string>(); yield break; } var firstArray = arrayList[0]; var remainingArrays = arrayList.Skip(1); // 遍历第一个数组的每个元素,和剩余数组的递归结果组合 foreach (var item in firstArray) { foreach (var subCombination in CrossJoinRecursive(remainingArrays)) { yield return new[] { item }.Concat(subCombination).ToArray(); } } }
代码说明:
- 当没有剩余数组时,返回空数组作为递归的“基础组合”。
- 对于每个数组,先取第一个数组的元素,再递归得到剩下数组的所有组合,最后把当前元素和每个子组合拼接,得到完整的组合结果。
注意事项
- 如果输入的数组数量为0,两种方法都会返回一个包含空数组的集合(你可以根据需求调整这个行为)。
- 笛卡尔积的结果数量是所有数组长度的乘积,当数组数量多或每个数组元素多的时候,结果会非常庞大,要注意内存和性能问题。
内容的提问来源于stack exchange,提问作者Asken
相关产品推荐
相关产品推荐

