Scala 在case类列表上使用reduceLeft/foldLeft的更好方法

Scala 在case类列表上使用reduceLeft/foldLeft的更好方法,scala,Scala,我的意图很简单:从用户对象列表中获取电子邮件的逗号分隔值。 我在Java中使用for循环和if-else条件完成了这项工作 现在我想在Scala中实现它,所以我尝试了这个 case class User(name: String, email: String) val userList = List(User("aaa", "aaa@aaa.com"), User("bbb", "bbb@bbb.com"), Us

我的意图很简单:从用户对象列表中获取电子邮件的逗号分隔值。 我在Java中使用for循环和if-else条件完成了这项工作

现在我想在Scala中实现它,所以我尝试了这个

case class User(name: String, email: String)

val userList = List(User("aaa", "aaa@aaa.com"),
                    User("bbb", "bbb@bbb.com"),
                    User("ccc", "ccc@ccc.com"))
现在

给予

ccc@ccc.com,bbb@bbb.com,aaa@aaa.com,
(注意末尾的逗号。)

给予

我试着像这样只使用
reduceLeft

val emailids = userList.reduceLeft((emails: String, user: User) => emails+", "+user.email)
但它会抛出编译错误

type mismatch;  found   : (String, User) => java.lang.String  required: (java.io.Serializable, User) => java.io.Serializable

那么,在上述情况下,是否有一种更好的方法可以使用
reduceLeft
而不使用
map
?在任何情况下,您的问题是您的
reduceLeft
唯一版本需要一个字符串作为其初始值。

否,
reduceLeft
是一个
foldLeft
,其中累加器是集合的第一个元素。在您的例子中,第一个元素是
用户
,您必须为迭代的下一步传递相同类型的参数。这就是为什么会出现类型不匹配。
您可以在惰性集合中进行映射,并按如下方式减少此操作:

val mailIds = userList.view map (_.email) reduceLeft (_ + "," + _)
这将为您提供
aaa@aaa.com,bbb@bbb.com,ccc@ccc.com
而不创建第二个集合。杰西·艾卡尔为此写了一篇非常好的文章

编辑

没有惰性集合的方法是通过以下方式删除最后一个逗号:

val rawMailIds = userList.foldLeft("")((acc, elem) => acc + elem.email + ",")
val mailIds = rawMailIds.substring(0, rawMailIds.length - 1)

“最好”的方法是使用
mkString
userList.map(u.email).mkString(“,”)
+1。特拉维斯,好建议。请把这句话写在答案中,Rajesh,但是我的评论并没有真正回答你提出的问题。在某种程度上,它使代码尽可能简单,同时可读性和易懂性。我想他不希望在计算字符串时生成另一个集合。或者
val mailIds=userList.tail.foldLeft(userList.head.email){(a:String,b:User)=>(b.email+“,”+a)}
(假设userList非空)
type mismatch;  found   : (String, User) => java.lang.String  required: (java.io.Serializable, User) => java.io.Serializable
val mailIds = userList.view map (_.email) reduceLeft (_ + "," + _)
val rawMailIds = userList.foldLeft("")((acc, elem) => acc + elem.email + ",")
val mailIds = rawMailIds.substring(0, rawMailIds.length - 1)