LINQ-запросы на возможно бесконечные списки - PullRequest
6 голосов
/ 30 марта 2009

В настоящее время я занимаюсь некоторыми задачами Project Euler, и более ранние часто связаны с такими вещами, как числа Фибоначчи или простые числа. Итерирование по ним кажется естественным соответствием для LINQ, по крайней мере, с точки зрения читабельности и воспринимаемой «элегантности» кода (я пытаюсь использовать специфичные для языка функции, где это возможно и применимо, чтобы почувствовать языки).

Моя проблема в том, что, если мне нужен только набор чисел до определенного предела, как мне лучше всего это выразить? В настоящее время я жестко запрограммировал соответствующий предел в итераторе, но мне бы очень хотелось, чтобы перечислитель возвращал список до тех пор, пока что-то извне не решит больше его не запрашивать, поскольку оно превышает определенный предел. Так что в основном у меня есть потенциально бесконечный итератор, но я беру только конечный набор чисел из него. Я знаю, что такие вещи тривиальны в функциональных языках, но мне интересно, допускает ли это и C #. Единственная другая идея, которая у меня была, - это иметь итератор простых чисел (long), который возвращает простые числа до определенного предела, аналогично для других последовательностей.

Есть идеи?

1 Ответ

10 голосов
/ 30 марта 2009

Большинство методов LINQ (Enumerable class) являются ленивыми. Так, например, нет ничего плохого в:

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

Вы можете использовать метод Take, чтобы ограничить результаты:

var 10squares = squares.Take(10);

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

Редактировать: То, что вам нужно избегать, это функции, которые возвращают "лениво", но должны потреблять все перечисляемое для получения результата. Например, группировка или сортировка:

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

(Это, вероятно, даст вам исключение OutOfMemory для 32-разрядного.)

...