Волшебство Мерзавца является всем, в чем Вы будете когда-либо нуждаться. Гарантируемый или Ваши деньги назад!
Нужная функция называется zipWith
, но она не является частью стандартной библиотеки. Это будет в 2.8 (ОБНОВЛЕНИЕ: По-видимому, нет, см. Комментарии).
foo zipWith((f: Double, b : Double) => f+b) bar
См. этот билет Trac .
Ленивый список - это не копия списка - это больше похоже на отдельный объект. В случае реализации отложенного zip-архива каждый раз, когда запрашивается следующий элемент, он захватывает элемент из каждого из двух входных списков и создает из них кортеж, а затем вы разбиваете кортеж на части с сопоставлением с образцом в вашей лямбде.
Таким образом, нет необходимости создавать полную копию всего список (-ов) ввода перед началом работы с ними. Это сводится к очень похожему шаблону распределения для любого приложения, работающего на JVM - множество очень недолговечных, но небольших распределений, с которыми JVM оптимизирована для работы.
Обновление: для ясности, вам нужно использовать потоки (ленивые списки), а не списки. У потоков Scala есть zip, который работает лениво, поэтому вам не следует преобразовывать вещи в списки.
В идеале ваш алгоритм должен быть способен работать с двумя бесконечными потоками, не взрываясь (при условии, что это не выполняет сворачивания
, конечно,
Что ж, отсутствие zip - это недостаток в Scala 2.7 Seq. Scala 2.8 имеет хорошо продуманную конструкцию коллекций, заменяющую случайный способ, которым коллекции, представленные в 2.7, появились (обратите внимание, что не все они были созданы одновременно с единым дизайном).
Теперь, когда вы Чтобы избежать создания временной коллекции, вам следует использовать «проекцию» в Scala 2.7 или «представление» в Scala 2.8. Это даст вам тип коллекции, для которого определенные инструкции, в частности map, flatMap и filter, не являются строгими. В Scala 2.7 проекцией списка является поток. В Scala 2.8 есть SequenceView для Sequence, но есть zipWith прямо там, в Sequence, он вам даже не понадобится.
Сказав, что, как уже упоминалось, JVM оптимизирована для обработки временного выделения объектов, а также, при работе в режиме сервера оптимизация времени выполнения может творить чудеса. Итак, не оптимизируйте преждевременно. Протестируйте код в условиях, в которых он будет запущен - и если вы не планировали запускать его в режиме сервера, подумайте еще раз, если ожидается, что код будет долгим, и выберите, когда / где / при необходимости.
РЕДАКТИРОВАТЬ
Что на самом деле будет доступно в Scala 2.8, так это:
(foo,bar).zipped.map(_+_)
ОБНОВЛЕНИЕ: Было указано (в комментариях), что этот «ответ» на самом деле не отвечает на задаваемый вопрос. Этот ответ будет отображаться для каждой комбинации из foo
и bar
, создавая элементы N x M вместо min ( M, N) по запросу. Итак, это неверно , но оставлено для потомков, поскольку это хорошая информация.
Лучший способ сделать это - использовать flatMap
в сочетании с map
. Код говорит громче, чем слова:
foo flatMap { f => bar map { b => f + b } }
В результате будет получен один Seq [Double]
, как и следовало ожидать. Этот шаблон настолько распространен, что Scala фактически включает некоторую синтаксическую магию, которая его реализует:
for {
f <- foo
b <- bar
} yield f + b
Или, альтернативно:
for (f <- foo; b <- bar) yield f + b
for {... } Синтаксис
- действительно самый идиоматический способ сделать это. Вы можете продолжить добавлять условия генератора (например, b <- bar
) по мере необходимости. Таким образом, если внезапно получается три Seq
, которые вы должны сопоставить, вы можете легко масштабировать свой синтаксис вместе с вашими требованиями (для создания фразы).
В Scala 2.8:
val baz = (foo, bar).zipped map (_ + _)
И работает более чем с двумя операндами одинаково. Т.е. затем вы можете продолжить это с помощью:
(foo, bar, baz).zipped map (_ * _ * _)