/ / scala map collect to odpowiednik groovy map collect - scala, groovy

scala map collect to odpowiednik groovy map collect - scala, groovy

Chcę listę wszystkich wartości dla określonego klucza w zagnieżdżonej mapie. Mam piękny, piękny przykład, jak poniżej.

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)
}
}
}

Wydajność

white shirt
blue pants
blue shirt
blue shirt
brown pants
blue converse

Chcę tej implementacji w scala, nie mogłem zrobić tego naturalnie jak w 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
}
}

Otrzymuję następujący błąd kompilacji w spłaszczeniu

Error:(25, 11) No implicit view available from java.io.Serializable => scala.collection.GenTraversableOnce[B].
items.flatten
^

Ponadto moim założeniem był rodzaj items zmienna powinna być List[List[String]], nie, scala kompilator krzyczy, że powinno być Iterable[Serializable]. Przynajmniej, Iterable[Iterable[String]] ma sens, ale skąd się bierze Serializable?

Kiedy nadaję mu typ,

val items : Iterable[Serializable] = retailPackages.map(p => p._2).map(it => it("items"))

To mówi Iterable[Serializable] doesn"t conform to Iterable[Serializable]

Odpowiedzi:

1 dla odpowiedzi № 1

Możesz przymusić przedmioty z Serializable do 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", "")

A później flatten Prace:

@ 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")

lub na jednej mapie:

@ 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")

0 dla odpowiedzi nr 2

Powoduje to opakowania detaliczne jest typu mieszanego:

Map(
String -> Map (
String -> List,
String -> Date
)
)

więc podczas mapowania "przedmiotów", nie może wnioskować o tym przedmiotów wpisz, możesz użyć case dopasować do przedmiotów rodzaj:

retailPackages.map(i => i._2("items")).flatMap{case l: List[String] => l}

Sugestia: użyj klasy case dla twojego elementu, np .:

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)