2016-12-22 9 views
2

::演算子でリストを作成しようとすると空リストになります。私のコードは次のようになります:スカラでループを作成してリストを作成

def getAllInfo(locks: List[String]): List[LockBundle] = DB.withTransaction { implicit s => 
    val myList = List[LockBundle]() 
    locks.foreach(
    l => findForLock(l) :: myList 
) 
    myList 
} 

def findForLock(lock: String): Option[LockBundle] = { ... } 

何か提案がありますか?

答えて

7

使用flatMap

locks.flatMap(l => findForLock(l)) 

あなたのコードは

def getAllInfo(locks: List[String]): List[LockBundle] = DB.withTransaction { implicit s => 
    locks.flatMap(l => findForLock(l)) 
} 

また、あなたがmapflattenを使用することができなりました。このようなものlocks.map(l => findForLock(l)).flatten

機能プログラミングはすべて変換に関するものです。あなたの関数findForLockである変換を使用して、既存のリストを別のリストに変換するだけで済みます。ので、あなたのコードのすべてのforeachリターンUnit

val myList = List[LockBundle]() 
    locks.foreach(
    l => findForLock(l) :: myList 
) 
    myList 

まず付き

問題は、あなたが側には、変換操作を行うとないためのforeachを使用しています。変換が必要なので、foreachを使用しないでください。

次に、findForLock(l) :: myListに値が与えられますが、生成された値を格納している人がいないため無視されます。したがって、値を格納するためにaccumulatorを使用し、再帰の場合には関数のパラメータとして渡します。

あなたはあなたの方法で行いたい場合は、あなたのコード

修正。アキュムレータを使用する必要があります。

最初にあなたのタイプを修正してくださいfindForLock(l)Optionを返します。リストのタイプはList[LockBundle]ですので、リストタイプをList[Option[LockBundle]]に変更してください。

List[LockBundle]List[Option[LockBundle]]から得るにはflattenList[Option[LockBundle]]にしてください。下記のコードスニペットを参照してください

var myList = List[Option[LockBundle]]() 
    locks.foreach(
    l => myList = findForLock(l) :: myList 
) 
    myList.flatten 

上記の方法は機能しないため、お勧めしません。

+1

http://www.flatmapthatshit.com/ –

2

foreachコンビネータは各要素にクロージャを指定しているので、コードは機能しませんが、ここでは式findForLock(l) :: myListを捨てて返します。

pamuが示唆したように、あなたはfindForLockによって返された値に各要素をマッピングし、それがNoneだ場合、それはSomeオア・ナッシングだ場合は、リストの要素にOptionを回すそのリストを、平らにする機能にflatMapを使用することができます。

あなたが与えられたモナド(つまり、この場合にはListまたはOptionである)と同じ型を返す場合にのみ、一般flatMap作品にOptionからSeqへの暗黙的な変換があるので、これはのみ動作することに注意してください。

関連する問題