2010-03-06 4 views
3

Я играю с использованием LINQ to Objects для мультиплексирования и демультиплексирования, но мне кажется, что это довольно сложная проблема.Mux & Demux w/LINQ

Смотреть это демультплексора подпись:

public static IEnumerable<IEnumerable<TSource>> Demux<TSource>(this IEnumerable<TSource> source, int multiplexity) 

На абстрактном уровне это легко, но в идеале хотелось бы

  • остаются ленив для потока исходного
  • остаются ленив для каждого мультиплексного потока
  • не повторять те же элементы

Как вы это сделаете?

Я немного устал, так что может быть моя концентрация не удается мне здесь ...

ответ

2

Предполагая, что вы хотите (0, 1, 2, 3), в конечном итоге, как (0, 2) и (1, 3) при демультиплексировании на два потока вы в принципе не можете делать это без буферизации. Вы могли буфер только при необходимости, но это было бы сложно. В общем, вы должны быть в состоянии справиться с двумя противоположными способами с помощью вызова ...

Getting как итераторы, и чтение один элемент из каждого из них:

// Ignoring disposing of iterators etc 
var query = source.Demux(2); 
var demuxIterator = query.GetEnumerator(); 
demuxIterator.MoveNext(); 
var first = demuxIterator.Current; 
demuxIterator.MoveNext(); 
var second = demuxIterator.Current; 
first.MoveNext(); 
Console.WriteLine(first.Current); // Prints 0 
second.MoveNext(); 
Console.WriteLine(second.Current); // Prints 1 

или получить один итератор, то чтение оба предмета:

// Ignoring disposing of iterators etc 
var query = source.Demux(2); 
var demuxIterator = query.GetEnumerator(); 
demuxIterator.MoveNext(); 
var first = demuxIterator.Current; 
first.MoveNext(); 
Console.WriteLine(first.Current); // Prints 0 
first.MoveNext(); 
Console.WriteLine(first.Current); // Prints 2 

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

Вы можете иметь дело с IList<T> вместо IEnumerable<T>? Это «сломает» остальную часть LINQ для объектов, правда - ленивые прогнозы и т. Д. Остались бы в прошлом.

Обратите внимание, что это очень похоже на проблемы, такие операции, как GroupBy есть - они отложены, но не ленитесь: как только вы начнете читать из GroupBy результата, он читает все входные данные.

+0

Да, я могу определить его, но мне нравится, поскольку это проект хобби. Но в том же духе я хочу иметь оптимальное представление. Но я думаю, что на языке C# отсутствует основной механизм, чтобы это произошло. Это довольно интересный случай для проверки выразительности языка, который я думаю. Хороший вопрос о GroupBy. Было бы замечательно, если бы у нас была настоящая лень. А также исключения - да, это еще более сложно, потому что вы не можете использовать «использование», когда не знаете, сколько вложенных потоков вам нужно иметь.

+0

Я думаю, что вы правы с буферизацией. Возможно, создайте пользовательский IList с фиксированным набором элементов, каждый из которых будет работать с таким же перечислимым и уважаемым порядком. Жаль, что вы не можете выразить это напрямую, но это, вероятно, достаточно хорошо. –

+0

@Bent: Дело не в том, что чего-то не хватает в языке - это фундаментальное несоответствие между тем, что вы пытаетесь сделать, и природой исходного формата мультии «только вперед».Когда у вас есть два итератора (по одному для каждой из демонстрационных последовательностей), вызывающий может запросить следующий элемент из любого из них - как вы ожидаете справиться с этим, если у вас нет случайного доступа и вы не хотите буферизовать или пропустить данные? –

 Смежные вопросы

  • Нет связанных вопросов^_^