如何用 LINQ 重写笛卡尔积

Posted

技术标签:

【中文标题】如何用 LINQ 重写笛卡尔积【英文标题】:How to rewrite cartesian product with LINQ 【发布时间】:2021-07-17 02:15:27 【问题描述】:

我有三个函数,一个使用来自 2 个数组的循环生成笛卡尔积,另一个使用来自 3 个数组的循环,以及一个使用 LINQ 和 2 个数组生成笛卡尔积。我想编写一个 LINQ 解决方案来获得 3 个数组。

        private static string[][] CartesianProductSmart(string[] arr1, string[] arr2)
        
            // for each s1 in arr1, extract arr2, 
            // then pass s1 and s2 into a newly-made string array.
            return arr1.SelectMany(s1 => arr2, (s1, s2) => new string[]  s1, s2 )
                .ToArray();
        
        private static string[][] CartesianProductDumb(string[] arr1, string[] arr2)
        
            // the dumb way; nested foreach
            string[][] combos = new string[arr1.Length * arr2.Length][];

            int ii = 0;
            foreach (var strOne in arr1)
            
                foreach (var strTwo in arr2)
                
                    string[] combo = new string[2];

                    combo[0] = strOne;
                    combo[1] = strTwo;
                    combos[ii] = combo;

                    ii++;
                
            
            return combos;
        
        private static string[][] CartesianProductDumbX3(string[] arr1, string[] arr2, string[] arr3)
        
            // the dumb way; nested foreach
            string[][] combos = new string[arr1.Length * arr2.Length * arr3.Length][];

            int ii = 0;
            foreach (var strOne in arr1)
            
                foreach (var strTwo in arr2)
                
                    foreach (var strThree in arr3)
                    
                        string[] combo = new string[3];

                        combo[0] = strOne;
                        combo[1] = strTwo;
                        combo[2] = strThree;
                        combos[ii] = combo;

                        ii++;
                    
                
            

            return combos;
        

前两个函数的行为相同 - 它们都返回 2 个数组的笛卡尔积。第三个是用三个数组做的,我怎样才能用 LINQ 重写那个函数? (最终我想写它以便我可以给它任何数组编号,但现在只有 3 就足够了。

【问题讨论】:

Just for reference. 【参考方案1】:

我不确定这是否是您要查找的内容,但它对我来说似乎是最简单和最易读的:

private static string[][] CartesianProductLinq(string[] arr1, string[] arr2,
    string[] arr3)

    return (from s1 in arr1
        from s2 in arr2
        from s3 in arr3
        select new[] s1, s2, s3).ToArray();

如果您更喜欢方法链语法,它可能类似于:

private static string[][] CartesianProductLinq(string[] arr1, string[] arr2, 
    string[] arr3)

    return arr1
        .SelectMany(s1 => arr2, (s1, s2) => new s1, s2)
        .SelectMany(result => arr3, (result, s3) => new[] result.s1, result.s2, s3)
        .ToArray();

请注意,方法名称已更改,因为 Linq 并非天生“聪明”,循环也并非天生“愚蠢”(在某些情况下,循环可能更有效)

【讨论】:

以上是关于如何用 LINQ 重写笛卡尔积的主要内容,如果未能解决你的问题,请参考以下文章

什么是笛卡尔积?

笛卡尔积

数据库笛卡尔积

笛卡尔积请具体解释一下.

笛卡尔乘积的意义

笛卡尔积举例分析