2014-04-26 52 views
0

我想轉換for循環:轉換嵌套循環中的LINQ聲明

for (int i = 100; i < 1000; i++) 
{ 
    for (int j = 100; j < 1000; j++) 
    { 
     if (IsPalindrome(i * j)) 
     { 
      palindromes.Add(i * j); 
     } 
    } 
} 

// For some reason the list is not sorted correctly, but when sorted it works. 
palindromes.Sort(); 
Console.WriteLine(palindromes.Last()); 

成一個單一的LINQ聲明,我搞亂了,雖然乘法,這是我到目前爲止,不幸的是,它似乎並沒有正確地增加,導致錯誤的數字收集。

var palis = Enumerable.Range(100, 999) 
         .Select(n => n * Enumerable.Range(100, 999) 
               .Aggregate((ctr, num) => ctr++)) 
         .Where(n => IsPalindrome(n)).Max(); 

回答

2

Réda Mattar's answer是接近的,但也有一些問題吧:

  1. Enumerable.Range第二個參數是整數返回的數量。這應該是900(因爲你的循環從100到999)。
  2. 從高範圍開始,並簡單地返回找到的每個值j的第一個迴文,而不是通過每個可能的整數組合都會更有效。

我建議稍微不同的形式:

var maxPalindrome = 
    (from i in Enumerable.Range(1, 900) 
    select (from j in Enumerable.Range(1, 900) 
      let p = (1000 - i) * (1000 - j) 
      where IsPalindrome(p) 
      select p).FirstOrDefault()).Max(); 
Console.WriteLine(maxPalindrome); 

但使用LINQ通常開銷在效率方面。

int maxPalindrome = 0; 
for(int i = 999; i >= 0; i--) 
{ 
    for(int j = 999; j >= 0; j--) 
    { 
     var p = i * j; 
     if (p <= maxPalindrome) 
     { 
      break; 
     } 
     if (IsPalindrome(p)) 
     { 
      maxPalindrome = p; 
      break; 
     } 
    } 
} 

Console.WriteLine(maxPalindrome); 

快速基準給出如下結果(10項研究):

  • 這種方法可以更有效的通過採取上述建議,並簡單地重寫你的for -loop這樣進行原代碼:04.14s
  • REDA感澈的方法:05.59s
  • 我的LINQ的方法:02.95s
  • for -loop方法:0.04秒

正如你所看到的,for循環提供了最好的性能。但是,效率不應該成爲您唯一的擔憂。一般而言,您應該選擇最容易閱讀和維護的解決方案。

+0

就像你說的,在這種情況下,我不是爲了提高效率,而是爲了讀性和「優雅」,我發現LINQ表達式通常比傳統方式更優雅。 –

2

你試過:

var palindromeMax = (from i in Enumerable.Range(100, 999) 
        from j in Enumerable.Range(100, 999) 
        where IsPalindrome(i * j) 
        select i * j).Max(); 
2

不要這樣做。由此產生的LINQ表達式比您開始使用的代碼更難理解。以其他答案爲例 - 很難獲得這個LINQ表達式,並且很難準確理解它的作用。

保留自己的代碼 - 沒關係。