Есть ли реализации оператора последовательности в .NET 4.0? - PullRequest
2 голосов
/ 29 июня 2010

Под этим я подразумеваю сходство с объединением Linq, группой, отдельным и т. Д., Работающим только с последовательностями значений, а не с коллекциями.

Разница между последовательностью и коллекцией заключается в том, что последовательность может быть бесконечнойв длину, тогда как коллекция конечна.

Позвольте мне привести пример:

var c1 = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var c2 = FunctionThatYieldsFibonacciNumbers();

var c3 = c1.Except(c2);

Это не работает.Реализация Except не работает на том основании, что числа в любой коллекции будут строго возрастать или убывать, поэтому сначала она пытается собрать все значения из второй коллекции в набор (или подобный), и только после этогоначните перечислять первую коллекцию.

Если предположить, что вышеприведенная функция является просто циклом while, который не завершается, пока вы не перестанете явно перечислять ее, приведенный выше код завершится с исключением из-за нехватки памяти.

Но, учитывая, что у меня есть коллекции, которые считаются строго восходящими или нисходящими, существуют ли уже какие-либо реализации в .NET 4.0, которые могут выполнять:

  1. Дайте мне все общие значенияобоим (внутреннее соединение)
  2. Дайте мне все значения обоих (объединение / внешнее соединение)
  3. Дайте мне все значения в последовательности # 1, которая не находится в последовательности # 2

Мне нужен этот тип функциональности, связанный с системой планирования, которую я должен построить, где мне нужно делать такие вещи, как:

c1 = the 1st and 15th of every month from january 2010 and onwards
c2 = weekdays from 2010 and onwards
c3 = all days in 2010-2012
c4 = c1 and c2 and c3

Это, в основном, дало бы мне каждый 1-й и 15-й числа каждого месяца в период с 2010 по 2012 гг., Но только тогда, когда эти даты приходятся на рабочие дни.

С такими функциями было бы намного проще генерировать рассматриваемые значения безявно приходится создавать коллекции из них.В приведенном выше примере для построения первых двух коллекций необходимо знать ограничение третьей коллекции, и примеры могут стать гораздо более сложными, чем приведенные выше.

Ответы [ 2 ]

2 голосов
/ 29 июня 2010

Я бы сказал, что операторы LINQ уже работают с общими последовательностями, но они не предназначены для работы специально для монотонных последовательностей, что у вас здесь есть.

Это не будетя подозреваю, что слишком сложно писать такие вещи, но я не верю, что что-то встроено;Насколько я могу судить, в System.Interactive нет ничего для этого сценария.

1 голос
/ 29 июня 2010

Вы можете рассмотреть модуль Seq для F # , который автоматически вызывается с помощью специальных конструкций языка F #, таких как 1 .. 10, которые генерируют последовательность.Он поддерживает бесконечные последовательности , как вы описываете, потому что он позволяет ленивую оценку.Использование F # может или не может быть тривиальным в вашей ситуации.Однако не должно быть слишком сложно использовать модуль Seq непосредственно из C # (но я сам не пробовал).

После в этом примере Мандельброта показан способ использования бесконечногопоследовательности с C #, скрывая yield.Не уверен, что это приблизит вас к тому, что вы хотите, но это может помочь.

РЕДАКТИРОВАТЬ
Хотя вы уже прокомментировали, что это не стоит в вашем текущем проекте, и приняли ответна ваш вопрос я был заинтригован этой идеей и придумал маленький пример.

Выглядело это довольно тривиально и хорошо работает в C # с .NET 3.5 и .NET 4.0, просто включив FSharp.Core.dll ( загрузите его для .NET 3.5 ) на вашРекомендации.Вот готовый пример бесконечной последовательности, реализующей ваш первый вариант использования:

// place in your using-section:
using Microsoft.FSharp.Collections;
using Microsoft.FSharp.Core;

// [...]

// trivial 1st and 15th of the month filter, starting Jan 1, 2010.
Func<int, DateTime> firstAndFifteenth = (int i) =>
{
    int year = i / 24 + 2010;
    int day = i % 2 != 0 ? 15 : 1;
    int month = ((int)i / 2) % 12 + 1;
    return new DateTime(year, month, day);
};

// convert func to keep F# happy
var fsharpFunc = FSharpFunc<int, DateTime>.FromConverter(
                   new Converter<int, DateTime>(firstAndFifteenth));

// infinite sequence, returns IEnumerable
var infSeq = SeqModule.InitializeInfinite<DateTime>(fsharpFunc);

// first 100 dates
foreach (var dt in infSeq.Take(100))
    Debug.WriteLine("Date is now: {0:MM-dd-yyy}", dt);

Вывод соответствует ожидаемым, первые несколько строк примерно так:

Date is now: 01-01-2010
Date is now: 01-15-2010
Date is now: 02-01-2010
Date is now: 02-15-2010
Date is now: 03-01-2010
...