Существуют ли реализации оператора последовательности в .NET 4.0?

При этом я имею в виду, что это похоже на соединение 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 год, но только тогда, когда эти даты выпадают на будние дни.

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


person Lasse V. Karlsen    schedule 29.06.2010    source источник
comment
Эй, @Abel, спасибо, что научил меня чему-то новому о переполнении стека :) Я не знал, что можно удалить форматирование, добавив предварительные теги! Оооо, не терпится вернуться и исправить несколько ответов сейчас.... Надо сопротивляться!   -  person Lasse V. Karlsen    schedule 29.06.2010
comment
Пожалуйста :). (OT) Обратите внимание, что <pre> должен быть в начале строки и сам по себе.   -  person Abel    schedule 29.06.2010
comment
Да, и я заметил, когда редактировал свой ответ указателя, что мне нужно избегать вещей, которые обычно обрабатываются блоками кода, например   -  person Lasse V. Karlsen    schedule 29.06.2010


Ответы (2)


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

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

person Jon Skeet    schedule 29.06.2010
comment
Я уже на пути к их написанию, я только что столкнулся с методом Except, который я планировал назвать своим, но, конечно, это не сработает, поэтому я протестировал его, и он терпит неудачу с вне- исключение памяти, поэтому для моих случаев его нельзя использовать. Все, что я хотел знать, это то, что я лаял не на то дерево. - person Lasse V. Karlsen; 29.06.2010
comment
Я предполагаю, что я уберу здесь синтаксис метода расширения, чтобы было ясно, что это не Linq, тогда не будет конфликта имен. - person Lasse V. Karlsen; 29.06.2010

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

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

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

Это оказалось довольно тривиально и хорошо работает на 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
person Abel    schedule 29.06.2010
comment
Определенно стоит посмотреть, но, к сожалению, не вариант для этого конкретного проекта. - person Lasse V. Karlsen; 29.06.2010