我想要嵌套地图中特定键的所有值列表。我在groovy中有一个非常漂亮的例子,如下所示。
class HashTableExperiment {
static def retailPackages = [
"package1": [
"items" : ["white shirt", "blue pants", "blue shirt"],
"shippingDate": new Date(2016, 10, 28)
],
"package2": [
"items" : ["blue shirt", "brown pants", "blue converse"],
"shippingDate": new Date(2016, 11, 23)
]
]
static def itemInventory() {
retailPackages.entrySet().collect {it.value.items}.flatten()
}
static def main(String[] args) {
itemInventory().each {
println(it)
}
}
}
输出
white shirt
blue pants
blue shirt
blue shirt
brown pants
blue converse
我想在scala中实现这个实现,不能像groovy那样自然地做到。
object MapExperiment {
val retailPackages = Map(
"package1" -> Map(
"items" -> List("white shirt", "blue pants", ""),
"shippingDate" -> new Date(2016, 10, 28)
),
"package2" -> Map(
"items" -> List("blue shirt", "brown pants", "blue converse"),
"shippingDate" -> new Date(2016, 11, 23)
)
)
def itemInventory(): Unit = {
val items = retailPackages.map(p => p._2).map(it => it("items"))
items.flatten
}
}
我在flatten中得到以下编译错误
Error:(25, 11) No implicit view available from java.io.Serializable => scala.collection.GenTraversableOnce[B].
items.flatten
^
另外,我的假设是items
变量的类型应为List[List[String]]
,nope,scala编译器应该是Iterable[Serializable]
。至少,Iterable[Iterable[String]]
是有意义的,但Serializable来自哪里?
当我给它一个类型时,
val items : Iterable[Serializable] = retailPackages.map(p => p._2).map(it => it("items"))
它说Iterable[Serializable] doesn't conform to Iterable[Serializable]
答案 0 :(得分:1)
您可以强制从Serializable
到List[String]
:
@ MapExperiment.retailPackages("package1")("items")
res11: Object with java.io.Serializable = List(white shirt, blue pants, )
@ MapExperiment.retailPackages("package1")("items").asInstanceOf[List[String]]
res12: List[String] = List("white shirt", "blue pants", "")
然后flatten
有效:
@ MapExperiment.retailPackages map { _._2 } map { _("items").asInstanceOf[List[String]] } flatten
res13: collection.immutable.Iterable[String] = List("white shirt", "blue pants", "", "blue shirt", "brown pants", "blue converse")
或在单个地图中:
@ MapExperiment.retailPackages map { _._2("items").asInstanceOf[List[String]] } flatten
res14: collection.immutable.Iterable[String] = List("white shirt", "blue pants", "", "blue shirt", "brown pants", "blue converse")
答案 1 :(得分:0)
这是因为 retailPackages 是混合类型:
Map(
String -> Map (
String -> List,
String -> Date
)
)
因此,当映射“项目”时,它无法推断项类型,您可以使用case
来匹配项类型:
retailPackages.map(i => i._2("items")).flatMap{case l: List[String] => l}
建议是:使用案例类作为元素,例如:
case class MyObject(items: List[String], shippingDate: Date)
val retailPackages = Map(
"package1" -> MyObject(List("white shirt", "blue pants", ""), new Date(2016, 10, 28))
,
"package2" -> MyObject(List("blue shirt", "brown pants", "blue converse"),new Date(2016, 11, 23))
)
retailPackages.flatMap(i => i._2.items)