打破使用Enumerable.Range </int>的IEnumerable <int>查询

时间:2009-04-25 18:24:34

标签: c# linq range ienumerable

我有以下IEnumerable LINQ查询:

var query = from p in Enumerable.Range(2, 1000000)
let sumofPowers = from ch in p.ToString()
                  let sumOfPowers = Math.Pow(Convert.ToDouble(ch.ToString()), 5)
                  select sumOfPowers
where p == sumofPowers.Sum()
select p;

它找到所有数字的总和,可以写成数字的五次幂之和。这是项目欧拉Problem 30

它可以正常工作。我知道这是挑剔,但范围让我烦恼。 我基本上已经猜到它已经找到了1,000,000的正确结果,所以我让它停在那里。在这种情况下,数量就足够了。

但它只是一个硬编码的“随机”数字。 如果您查看代码,您会发现只要p == sumofPowers.Sum()为真,就不再需要再次运行循环了。

我知道yield可以在其他情况下执行此操作,而break可以在正常循环中运行 - 那么在这种情况下你能做些什么吗?

3 个答案:

答案 0 :(得分:4)

您可以使用First()运算符来突破。

由于LINQ确实延迟计算,因此直到达到p == sumofPowers.Sum()的点,然后返回第一个元素。只需将整个查询包装在(...)中.First();返回第一个值。

此外,当你在它时,没有必要转换为字符串然后转换为双 - 你可以直接从int转换 - &gt;加倍,避免字符串转换。

答案 1 :(得分:1)

class Program
{
    static void Main(string[] args)            
    {
        ulong sum, gh = 0;

        for (ulong i = 2; i <= 355000; i++)
        {
            string s = Convert.ToString(i);
            sum = 0;
            int ddd = s.Length;
            for (int j = 0; j < ddd; j++)
            {
                //sum +=(int)Math.Pow(Convert.ToInt32(s[j]), 4);
                ulong g = Convert.ToUInt64(Convert.ToString(s[j]));
                sum = sum + (ulong)Math.Pow(g, 5);
            }
            // Console.WriteLine(sum);
            if (sum == i)
            {
                gh += i;
            }
        }
        Console.WriteLine(gh);

        Console.ReadKey();
    }
}

答案 2 :(得分:0)

LINQ不是解决所有问题的方法。您的问题只有一个由其解决方案定义的范围,因此从“查询”的角度来看,没有范围,这使得它不适用于已知的集合操作,如LINQ和标准的IEnumerable扩展方法。使用yield语句可以做得更好(并生成更易读的代码)。