didierd ' ответ почти идеален, но, увы, я думаю, что один может немного его улучшить. Он занимается созданием всех списков, и транспонирование также является довольно сложной операцией. Если вы можете обрабатывать все данные одновременно, это вполне может быть достаточно.
Однако я использую Stream
и использую небольшой трюк, чтобы избежать переноса.
Прежде всего, группировка такая же, только я превращаю вещи в потоки:
def getChannels[T](input: Iterator[T], elementsPerSample: Int, numOfChannels: Int) =
input.toStream.grouped(elementsPerSample).toStream.grouped(numOfChannels).toStream
Далее я дам вам функцию для извлечения одного канала из этого:
def streamN[T](s: Stream[Stream[Stream[T]]])(channel: Int) = s flatMap (_(channel))
С их помощью мы можем декодировать потоки следующим образом:
// Sample input
val input = List('A1, 'A2, 'B1, 'B2, 'C1, 'C2, 'D1, 'D2, 'A3, 'A4, 'B3, 'B4, 'C3, 'C4, 'D3, 'D4)
// Save streams to val, to avoid recomputing the groups
val streams = getChannels(input.iterator, elementsPerSample = 2, numOfChannels = 4)
// Decode each one
def demuxer = streamN(streams) _
val aa = demuxer(0)
val bb = demuxer(1)
val cc = demuxer(2)
val dd = demuxer(3)
Это вернет отдельные потоки для каждого канала без , имеющего весь поток под рукой. Это может быть полезно, если вам нужно обрабатывать ввод в реальном времени. Вот некоторый источник входных данных, чтобы проверить, как далеко он вводит данные для определенного элемента:
def source(elementsPerSample: Int, numOfChannels: Int) = Iterator.from(0).map { x =>
"" + ('A' + x / elementsPerSample % numOfChannels).toChar +
(x % elementsPerSample
+ (x / (numOfChannels * elementsPerSample)) * elementsPerSample
+ 1)
}.map { x => println("Saw "+x); x }
Затем вы можете попробовать что-то вроде этого:
val streams = getChannels(source(2, 4), elementsPerSample = 2, numOfChannels = 4)
def demuxer = streamN(streams) _
val cc = demuxer(2)
println(cc take 20 toList)
val bb = demuxer(1)
println(bb take 30 toList)