如何在Scala中将对象列表转换为具有两个字段的映射?

9
我是一名Java程序员,正在使用Play框架。我有一个方法,它接收一个Map并将其转换为HTML选择元素。我曾经有一个一行代码,可以将对象列表转换为两个对象字段id和name的映射。但是,我的Scala编程能力不足,我竟然忘记了如何编写这段代码的语法。
我大致记得代码如下:
organizations.all.map {org => /* org.prop1, org.prop2 */ }

有人可以完成注释部分吗?

2个回答

15
我建议如下:

我建议:

map { org => (org.id, org.name) } toMap

e.g.

scala> case class T(val a : Int, val b : String)
defined class T

scala> List(T(1, "A"), T(2, "B"))
res0: List[T] = List(T(1,A), T(2,B))

scala> res0.map(t => (t.a, t.b))
res1: List[(Int, String)] = List((1,A), (2,B))

scala> res0.map(t => (t.a, t.b)).toMap
res2: scala.collection.immutable.Map[Int,String] = Map(1 -> A, 2 -> B)

1
.toMap,因为原始类型是List - om-nom-nom
那就是我忘记的那行代码。真是一种灵活的语言。 - evanjdooner

6

您也可以跳过中间步骤,直接使用Map,示例如下:

case class Org(prop1:String, prop2:Int)
val list = List(Org("foo", 1), Org("bar", 2))  
val map:Map[String,Int] = list.map(org => (org.prop1, org.prop2))(collection.breakOut)

使用collection.breakOut作为隐式的CanBuildFrom,可以基本上跳过从List获取Map的过程中的一步。

1
我发现你在这里的回答非常有趣,我从未听说过breakOut...顺便提供一些参考信息给那些也在学习的人:https://dev59.com/OXI-5IYBdhLWcg3wta1q - LaloInDublin
谢谢您的建议。然而,我尝试在Scala HTML模板中使用了您的代码变体list.map(org => (org.prop1, org.prop2))(collection.breakOut),但它返回了一个类型为scala.collection.immutable.IndexedSeq[(String, String)]的对象。我使用的代码是Organization.all.map(org => (org.id.toString, org.name))(collection.breakOut),其中Organization.all()是一个返回List<Organization>的Java方法。 - evanjdooner
1
@evanjdooner,你输入的val或var变量类型是否正确?它必须被明确地声明为Map类型,就像我的示例一样。 - cmbaxter
啊,我明白了。我忘记给变量赋值了,因为我把它作为参数传递了。我会按照你的方法尝试一下。 - evanjdooner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接