C# 使用LINQ求给定素数因子数组的数的除数

C# 使用LINQ求给定素数因子数组的数的除数,c#,.net,linq,math,C#,.net,Linq,Math,给定一个自然数的素因子数组,如何在原始数组上使用LINQ求除数的总数?我已经解决了这个问题的大部分,但我的LINQ语句有问题 数学背景: 一个数的素数因子是一个素数整数,它被均匀地分割成一个数而没有余数。e、 g.60的基本因子为2,2,3,5 一个数的除数是所有整数(素数或其他)都可以等分成不带余数的数。60的除数是1,2,3,4,5,6,10,12,15,20,30,60 我对求除数的总数感兴趣。60的除数总数是12 让我们用指数表示素因式分解: 60 = 2^2 * 3^1 * 5*1

给定一个自然数的素因子数组,如何在原始数组上使用LINQ求除数的总数?我已经解决了这个问题的大部分,但我的LINQ语句有问题


数学背景:

一个数的素数因子是一个素数整数,它被均匀地分割成一个数而没有余数。e、 g.60的基本因子为2,2,3,5

一个数的除数是所有整数(素数或其他)都可以等分成不带余数的数。60的除数是1,2,3,4,5,6,10,12,15,20,30,60

我对求除数的总数感兴趣。60的除数总数是12

让我们用指数表示素因式分解:

60 = 2^2 * 3^1 * 5*1
要求出给定数的素因子分解的除数总数,我们只需在每个指数上加1,然后将这些数相乘,如下所示:

(2 + 1) * (1 + 1) * (1 + 1) = 12;
这就是在给定一个数的素因式分解的情况下,求除数的方法

我目前掌握的代码:

我已经有了很好的代码来获得一个数的素数因子,所以我不关心这个问题使用LINQ,我想计算出除数的总数。我可以使用一些循环,但我正在尝试使用LINQ(如果可能的话)

我要:

  • 使用
    Distinct()
    查找数组中的唯一值
  • 使用
    Count()
    查找唯一值出现的时间(等于指数)
  • 使用
    Aggregate()
    函数将这些值相乘
以下是我的代码:

class Program
{
    static void Main(string[] args)
    {
        var primeFactors = new int[] { 2, 2, 3, 5 };
        Console.WriteLine(primeFactors.Distinct().PrintList("", ", "));
            //Prints: 2, 3, 5
        Console.WriteLine("[2]:{0} [3]:{1} [5]:{2}"
            , primeFactors.Count(x => x == 2)
            , primeFactors.Count(x => x == 3)
            , primeFactors.Count(x => x == 5)
            );
            //Prints: [2]:2 [3]:1 [5]:1

\\THIS IS WHERE I HAVE TROUBLE:

        Console.WriteLine(primeFactors.Distinct().Aggregate((total,next) =>  
            (primeFactors.Count(x => x ==next) + 1)* total));
            //Prints: 8


        Console.ReadLine();
    }
}
具体地说,我对这部分代码有问题:

primeFactors.Distinct().Aggregate((total,next) =>  
    (primeFactors.Count(x => x ==next) + 1)* total)
由于数组中的数字不是以
x^n
的形式存储的,而是以
n
数组中
x
的实例的形式存储的,因此我的想法是使用
Count()
来查找
n
应该位于
x
的不同数组中的内容。
Aggregate
函数用于迭代数组中的每个不同项,找到其
计数
+1,然后将其乘以总数。
Count
中的lambda表达式应该使用每个不同的数字作为参数(
next

上面的代码应该返回12,但是它返回8。在调试模式下,我很难“通过”LINQ,我不知道如何更好地编写这个


为什么我代码的这一部分没有像我预期的那样返回正确的除数数?是否有其他(更好)的方式使用LINQ来表达这一点?

如果我了解您想要做什么,您可能希望使用
GroupBy()

var primeFactors = new int[]{ 2, 2, 3, 5 };
var numFacs = primeFactors.GroupBy(f => f, f => f, (g, s) => s.Count() + 1)
                          .Aggregate(1, (x, y) => x * y);

如果我了解您想要做什么,您可能希望使用
GroupBy()

var primeFactors = new int[]{ 2, 2, 3, 5 };
var numFacs = primeFactors.GroupBy(f => f, f => f, (g, s) => s.Count() + 1)
                          .Aggregate(1, (x, y) => x * y);
试试这个:

int[] factors = new int[] { 2, 2, 3, 5 };
var q = from o in factors
        group o by o into g
        select g.Count() + 1;
var r = q.Aggregate((x, y) => x * y);
建议查询的具体问题是聚合调用无法对第一个元素进行计数(更不用说没有将计数增加1)。它错误的做法是取第一个因子,将其值(而不是计数+1)乘以下一个因子。

尝试以下方法:

int[] factors = new int[] { 2, 2, 3, 5 };
var q = from o in factors
        group o by o into g
        select g.Count() + 1;
var r = q.Aggregate((x, y) => x * y);

建议查询的具体问题是聚合调用无法对第一个元素进行计数(更不用说没有将计数增加1)。它错误的做法是取第一个因子,并将其值(而不是计数+1)乘以下一个因子。

+1然而,我更希望它是一个没有中间q变量的线性,这很好。我将其改写为:
primeFactors.GroupBy(f=>f)。选择(x=>x.Count()+1)。聚合((总计,下一个)=>next*total)
。为什么将count()+1放在select中可以正确工作,但在聚合中却不能正确工作?因为在聚合的第一次迭代中,您从两个基值开始,所以您需要同时计算它们,但此后您只需要计算“next”参数,因为第一个是聚合值。啊!有没有一种方法可以“播种”基值,从而将迭代应用于每个值?有,这是聚合的重载之一:)+1然而,我更希望它是一个没有中间q变量的线性,这很好。我将其改写为:
primeFactors.GroupBy(f=>f)。选择(x=>x.Count()+1)。聚合((总计,下一个)=>next*total)
。为什么将count()+1放在select中可以正确工作,但在聚合中却不能正确工作?因为在聚合的第一次迭代中,您从两个基值开始,所以您需要同时计算它们,但此后您只需要计算“next”参数,因为第一个是聚合值。啊!难道没有一种方法可以“播种”基值,从而将迭代应用于每个值吗?是的,这是聚合的重载之一:)您的答案非常有效。为什么在
GroupBy
子句中有3个lambda,而且(更重要的是)为什么前2个lambda是相同的?GroupBy函数只有这么多重载。第一个lambda标识分组所依据的密钥。第二个选项确定要为组中的每个项目选择的结果。第三种方法允许您将整个组(分组项列表)转换为单个结果,否则组列表就是结果。因此,前两个lambda是相同的,因为我希望选择每个项目而不改变它。我希望我可以省略第二个lambda,但是GroupBy没有相应的重载。你的答案很好。为什么在
GroupBy
子句中有3个lambda,而且(更重要的是)为什么前2个lambda是相同的?GroupBy函数只有这么多重载。第一个lambda标识分组所依据的密钥。第二种方法确定了对s的结果