Спасибо за автономную компиляцию кода в вашем вопросе.Я не думаю, что вы хотите сгладить петли, поскольку структура не плоская.Затем вам нужно использовать groupBy
для восстановления структуры.Также, если у вас есть «ноль -> Seq ()» в качестве элемента карты, он будет потерян.Использование этой простой карты позволяет избежать groupBy
и сохранить элементы, сопоставленные с пустыми последовательностями:
def loadMap(in: ObjectInputStream): Map[String, IndexedSeq[Int]] = {
val size = in.readInt
(1 to size).map{ _ =>
val key = in.readUTF
val nval = in.readInt
key -> (1 to nval).map(_ => in.readInt)
}(collection.breakOut)
}
Я использую breakOut
для генерации правильного типа, так как в противном случае я думаю, что компиляторы жалуются на универсальные Map
инеизменное Map
несоответствие.Вы также можете использовать Map() ++ (...)
.
Примечание. Я пришел к этому решению, запутавшись в цикле for и начав переписывать с использованием flatMap и map:
val tuples = (1 to size).flatMap{ _ =>
val key = in.readUTF
println("key " + key)
val nval = in.readInt
(1 to nval).map(_ => key -> in.readInt)
}
Я думаю, что вцикл for, что-то происходит, когда вы не используете какой-либо генератор.Я думаю, что это будет эквивалентно:
val tuples = for {
_ <- 1 to size
key = in.readUTF
nval = in.readInt
_ <- 1 to nval
value = in.readInt
} yield { key -> value }
Но это не тот случай, поэтому я думаю, что что-то упустил в переводе.
Редактировать: выяснил, что не так с одним циклом for.Короткая история: перевод определений внутри циклов for заставил оператор key = in.readUTF
вызываться последовательно перед выполнением внутреннего цикла.Чтобы обойти это, используйте view
и force
:
val tuples = (for {
_ <- (1 to size).view
key = in.readUTF
nval = in.readInt
_ <- 1 to nval
value = in.readInt
} yield { key -> value }).force
Проблема может быть более четко продемонстрирована с помощью этого фрагмента кода:
val iter = Iterator.from(1)
val tuple = for {
_ <- 1 to 3
outer = iter.next
_ <- 1 to 3
inner = iter.next
} yield (outer, inner)
Возвращает Vector((1,4), (1,5), (1,6), (2,7), (2,8), (2,9), (3,10), (3,11), (3,12))
который показывает, что все внешние значения оцениваются перед внутренними значениями.Это связано с тем, что он более или менее переводится в нечто вроде:
for {
(i, outer) <- for (i <- (1 to 3)) yield (i, iter.next)
_ <- 1 to 3
inner = iter.next
} yield (outer, inner)
Это сначала вычисляет все внешние iter.next
.Возвращаясь к исходному сценарию использования, все значения in.readUTF
будут вызываться последовательно до in.readInt
.