2011-08-09 2 views
23

У меня есть карта, которую мне нужно сопоставить с другим типом, и результат должен быть списком. У меня есть два способа (по-видимому) выполнить то, что я хочу, поскольку отображение карты на карте, как представляется, всегда приводит к карте. Предполагая, что у меня есть некоторые карты, которая выглядит как:Преобразование карты Scala в список

val input = Map[String, List[Int]]("rk1" -> List(1,2,3), "rk2" -> List(4,5,6)) 

Я могу либо сделать:

val output = input.map{ case(k,v) => (k.getBytes, v) } toList 

Или:

val output = input.foldRight(List[Pair[Array[Byte], List[Int]]]()){ (el, res) => 
    (el._1.getBytes, el._2) :: res 
} 

В первом примере я преобразовать тип, а затем вызвать ToList , Я предполагаю, что время выполнения - это что-то вроде O(n*2), а требуемое пространство - n*2. Во втором примере я конвертирую тип и генерирую список за один раз. Я предполагаю, что время выполнения составляет O(n), а требуемое пространство - n.

Вопрос в том, являются ли они по существу идентичными или второе преобразование сокращено на память/время/и т. Д.? Кроме того, где я могу найти информацию о стоимости хранения и времени выполнения различных конверсий scala?

Заранее спасибо.

ответ

23

Мой любимый способ сделать такого рода вещи, как это:

input.map { case (k,v) => (k.getBytes, v) }(collection.breakOut): List[(Array[Byte], List[Int])] 

С помощью этого синтаксиса, вы передаете в map строитель он должен восстановить полученный набор. (На самом деле, это не строитель, а фабрика строителей. Узнайте больше о Scala's CanBuildFrom s, если вы заинтересованы.) collection.breakOut может быть точно использован, если вы хотите изменить один тип коллекции на другой, делая map, flatMap и т. Д. единственная плохая часть состоит в том, что вам нужно использовать аннотацию полного типа, чтобы она была эффективной (здесь я использовал тип записи после выражения). Затем не создается промежуточная коллекция, и список создается , а.

+3

+1. Для тех, кто хочет понять, как работает 'breakOut', см. Отличный ответ Дэниела Собрала, http://stackoverflow.com/questions/1715681/scala-2-8-breakout/1716558#1716558 –

18

Mapping над целью в первом примере можно было сократить потребности в площади для большой карте:

val output = input.view.map{ case(k,v) => (k.getBytes, v) } toList 
+0

Об ленивых просмотров: http: // www .scala-lang.org/доку/файлы/сборники-апи/collections_42.html – Vadzim

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