2009-03-30 18 views
6

Actualmente estoy haciendo algunos problemas de Project Euler y los anteriores a menudo implican cosas como números de Fibonacci o números primos. Iterar sobre ellos parece ser un ajuste natural para LINQ, al menos en legibilidad y percepción de "elegancia" del código (estoy tratando de usar funciones específicas del lenguaje cuando sea posible y aplicable para tener una idea de los idiomas).Consultas de LINQ en listas posiblemente infinitas

Mi problema es que si solo necesito un conjunto de números hasta cierto límite, ¿cómo debería expresar esto? Actualmente he codificado el límite respectivo en el iterador, pero realmente me gustaría que el enumerador devuelva la lista hasta que algo afuera decida no consultarlo más, ya que está por encima de un cierto límite. Entonces, básicamente, tengo un iterador potencialmente infinito, pero solo tomo un conjunto finito de números de él. Sé que estas cosas son triviales en los lenguajes funcionales, pero me pregunto si C# también lo permite. La única otra idea que tenía era tener un iterador Primes (largo) que devuelve primos hasta cierto límite, del mismo modo para otras secuencias.

¿Alguna idea?

Respuesta

10

La mayoría de los métodos LINQ (clase Enumerable) son flojos. Así, por ejemplo, no hay nada de malo en:

var squares = Enumerable.Range(0, Int32.MaxValue).Select(x=>x*x); 

Usted puede utilizar el método Toma para limitar los resultados:

var 10squares = squares.Take(10); 

var smallSquares = squares.TakeWhile(x => x < 10000); 

Editar: Las cosas que hay que evitar son funciones que devuelven "perezosamente "pero tienen que consumir todo el enumerable para producir un resultado". Por ejemplo, agrupar o clasificar:

var oddsAndEvens = Enumerable.Range(0, Int32.MaxValue) 
          .GroupBy(x => x % 2 == 0); 
foreach (var item in oddsAndEvens) { 
    Console.WriteLine(item.Key); 
} 

(Eso probablemente le daremos un OutOfMemoryExeption de 32 bits.)

+0

Ah, bien, no sabía TakeWhile hasta ahora. Simplemente pensé que usar Where para seleccionar los números que quiero no funcionaría, ya que LINQ no tiene idea de que los números están aumentando, por ejemplo. Eso suena bien, de hecho :) – Joey

+0

+1, buen resumen. También traté de elaborar un poco sobre este tema: http://blog.casualdev.net/2009/10/linq-and-infinite-enumerations.html –