在Scala中循环并创建列表

时间:2016-12-22 12:22:58

标签: scala

当我尝试使用::运算符创建列表时,我将获得空列表。我的代码如下所示:

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] = { ... }

有什么建议吗?

2 个答案:

答案 0 :(得分:8)

使用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转换将现有列表转换为另一个列表。

您的代码存在问题

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

首先foreach返回Unit因此,您使用foreach进行副作用操作而不是转换。由于您需要转换,因此请勿使用foreach

接下来,findForLock(l) :: myList会为您提供一个值,但会被忽略,因为没有人存储生成的值。因此,为了存储值使用累加器并在递归的情况下将其作为函数参数传递。

更正您的代码

如果你想以自己的方式做。你需要使用累加器。

首先修复您的类型findForLock(l)返回Option,您的列表属于List[LockBundle]类型,因此请将列表类型更改为List[Option[LockBundle]]

要从List[LockBundle]获取List[Option[LockBundle]],请在flatten列表中执行List[Option[LockBundle]]。请参阅下面的代码段

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

以上方式不起作用,不推荐使用。

答案 1 :(得分:2)

您的代码不起作用,因为foreach组合器调用每个元素的闭包,但您在此处所做的只是返回被丢弃的表达式findForLock(l) :: myList

正如pamu建议的那样,您可以在函数上使用flatMap将每个元素映射到findForLock返回的值并展平该列表,如果它是Option,则将Some转换为列表的元素如果是None,则Option或一无所获。

请注意,这只是因为存在从SeqflatMap的隐式转换,通常List只有在返回与给定monad相同的类型时才有效(这种情况为Option//Here's the code typedef struct node{ bool is_word; struct node *children[27]; } node; unsigned int wsize=0; node * root; bool check(const char* word) { // TODO node *chrawler=root; for(int i=0;i<strlen(word)-1;i++) { int t; if(word[i]>=65&&word[i]<=90) { t=word[i]-'A'; } else if(isalpha(word[i])) t=word[i]-'a'; else t=26; if(chrawler->children[t]==NULL) return false; else chrawler=chrawler->children[t]; } if(chrawler->is_word) return true; return false; } // Load function bool load(const char* dictionary) { // TODO FILE *inptr=fopen(dictionary,"r"); if(inptr==NULL) { return false; } node *new_node=malloc(sizeof(node)); root=new_node; char * word=malloc((LENGTH+1)*sizeof(char)); int index=0; for(int c=fgetc(inptr);c!=EOF;c=fgetc(inptr)) { char ch=c; if(ch=='\n') { word[index]='\0'; index=0; node *chrawler=root; for(int i=1;i<strlen(word);i++) { int t; if(isalpha(word[i-1])) t=word[i-1]-'a'; else t=26; if(chrawler->children[t]==NULL) { node *new_node=malloc(sizeof(node)); chrawler->children[t]=new_node; chrawler=chrawler->children[t]; } else chrawler=chrawler->children[t]; } chrawler->is_word=1; wsize++; } else { word[index]=ch; index++; } } return true; } )。