我的意图很简单:从用户对象列表中获取逗号分隔的emaild值。 我在Java中用for循环和if条件完成了这个。
现在我想在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"))
现在
val mailIds = userList.foldLeft(""){(a: String, b: User) => ( b.email+","+a) }
给出
ccc@ccc.com,bbb@bbb.com,aaa@aaa.com,
(请注意最后的逗号。)
和
val mailids = userList.map(x => x.email).reduceLeft(_+","+_)
给出
aaa@aaa.com,bbb@bbb.com,ccc@ccc.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
?
答案 0 :(得分:2)
不,reduceLeft
是foldLeft
,其中累加器是集合的第一个元素。在您的情况下,第一个元素是User
,您必须为迭代的下一步传递相同类型的参数。这就是为什么你得到一个类型错配。
您可以在惰性集合中执行映射,并将其减少如下:
val mailIds = userList.view map (_.email) reduceLeft (_ + "," + _)
这将为您aaa@aaa.com,bbb@bbb.com,ccc@ccc.com
而不创建第二个集合。 Jessie Eichar为此写了一篇非常好的tutorial。
修改强>
没有延迟收藏的方法是删除最后一个逗号:
val rawMailIds = userList.foldLeft("")((acc, elem) => acc + elem.email + ",")
val mailIds = rawMailIds.substring(0, rawMailIds.length - 1)
答案 1 :(得分:0)
为什么不坚持使用map和reduce的组合?在任何情况下,您的问题是您的reduceLeft
版本只需要一个字符串作为其初始值。