There are no C# comaprable anonmyous classes in Scala (although they do exist, they are far less useful IMO). Alternatively, you can use a Tuple2[String, Int]
((String, Int)
) which has nice syntax sugar.
For convience, we can create a case class
of the PlanesLogRow
, which gives us a nice compact way for creating a class (note all values are immutable):
case class PlanesLogRow(flightDate: ZonedDateTime, origin: String, destination: String)
Now let's create a sequence of them:
val flights = Seq(
PlanesLogRow(ZonedDateTime.now(), "US", "Kiev"),
PlanesLogRow(ZonedDateTime.now().plusHours(2L), "US", "Prague"),
PlanesLogRow(ZonedDateTime.now().plusHours(4L), "Canada", "Prague")
)
From and to dates (I used java.time
for convenience):
val dateFrom = ZonedDateTime.now
val dateTo = ZonedDateTime.now().plusHours(5L)
Now, we can filter once (no need for two passes over the collection), group, and then output the result to a Map[String, Int]
:
val result: Map[String, Int] =
flights
.filter(logRow => logRow.flightDate.isAfter(dateFrom) && logRow.flightDate.isBefore(dateTo))
.groupBy(_.destination)
.map { case (location, logRows) => (location, logRows.length) }
Yields:
Map(Prague -> 2)
In Scala, unlike LINQ in C#, combinators over collections are strict, not lazy. This means that for every combinator you invoke (map
, filter
etc) there will be an allocation of a new collection. To get around this, you can use views which produce lazy collections:
val result =
flights
.view
.filter(logRow => logRow.flightDate.isAfter(dateFrom) && logRow.flightDate.isBefore(dateTo))
.groupBy(_.destination)
.map { case (location, logRows) => (location, logRows.length) }
Other then that, the naming convention for scala fields are camelCase, not PascalCase like C#.