2015-07-06 3 views
2

EDIT: Я нашел это What is Scala's yield? (особенно второй, самый популярный, ответ), чтобы быть очень поучительным после того, как принятый ответ решил мою проблему.Для цикла внутри .map() в scala: return type is "Unit"

==

У меня есть HashMap, которые я хочу итерацию в, и для каждого из ключей, использовать цикл для создания новых объектов.

Я пытаюсь получить список этих новых объектов, но мне всегда возвращается пустая последовательность «Единица». Я хотел бы лучше понять поведение моего кода.

case class MyObject(one: String, two: String, three: Int) 

val hm = new HashMap[String,Int] 

hm += ("key" -> 3) 
hm += ("key2" -> 4) 

val newList = hm.map { case (key,value) => 
    for (i <- 0 until value) { 
    new MyObject(key, "a string", i) 
    }}.toSeq 

результат:

newList:Seq[Unit] = ArrayBuffer((),()) 

Если я не использую любой цикл внутри .map(), у меня есть тип структуры я ожидал:

val newList = hm.map { case (key,value) => 
    new MyObject(key, "a string", value)}.toSeq 

результаты:

newList:Seq[MyObject] = ArrayBuffer(MyObject(key,host,3), MyObject(key2,host,4)) 
+0

Какой результат вы ожидали? – Bergi

+2

Вы не указали ключевое слово 'yield' в своем заявлении' map' – cmbaxter

ответ

7

Как я уже говорил в своем комментарии, вы отсутствуют yield для понимания в вашем заявлении map. Если вы не указали ключевое слово yield, то ваше понимание понимает чисто побочные эффекты и ничего не производит. Измените его на:

for (i <- 0 until value) yield { 

Теперь здесь, вы будете в конечном итоге с Seq[IndexedSeq[MyObject]]. Если вы хотите, чтобы в конечном итоге просто Seq[MyObject] то вы можете flatten так:

val newList = hm.map { case (key,value) => 
    for (i <- 0 until value) yield { 
    MyObject(key, "a string", i) 
    }}.toSeq.flatten 
} 

И на самом деле (как указывал @KarolS), вы можете сократить еще дальше, заменив map с flatMap и удалить явно flatten в конце:

val newList = hm.flatMap { case (key,value) => 
    for (i <- 0 until value) yield { 
    MyObject(key, "a string", i) 
    }}.toSeq 
} 
+1

Вместо '.map (...). Flatten' вы обычно можете делать' .flatMap (...) ', и обычно это быстрее. –

+0

@ KarolS, хороший момент, я добавлю к ответу ... – cmbaxter