如何在多个事物上进行模式匹配以进行理解

时间:2019-03-14 13:25:57

标签: scala pattern-matching slick

我有一个内在7的理解力。 7事物正在Slick中运行数据库查询,可能不会返回任何数据。当他们不返回任何数据时,我希望使用默认值。如果只有1的东西,我可以做以下事情,但是当我有7时该怎么做?

case class MyType(one: String, two: Int, three: Int)

//What I could do for 1 thing
for {
  thing1: Option[MyType] <- repo.queryForThing1()
}
yield {
  thing1 match {
   case Some(t) => MyOtherType(Seq(t))
   case None => MyOtherType(Seq(MyType("thing1", 0, 0)))
  }
}

//What do I do for when I have 7 things??
for {
  thing1: Option[MyType] <- repo.queryForThing1()
  thing2: Option[MyType] <- repo.queryForThing2()
  thing3: Option[MyType] <- repo.queryForThing3()
  thing4: Option[MyType] <- repo.queryForThing4()
  thing5: Option[MyType] <- repo.queryForThing5()
  thing6: Option[MyType] <- repo.queryForThing6()
  thing7: Option[MyType] <- repo.queryForThing7()
}
yield {
  thing1 match {
   case Some(t) => MyOtherType(Seq(t))
   case None => MyOtherType(Seq(MyType("thing1", 0, 0)))
  }
}

问题

如何为7件事图案匹配?每个thing<number>的默认值均为None

2 个答案:

答案 0 :(得分:1)

试试看!但这不是一个性感的代码:D

for {
  thing1: Option[String] <- repo.queryForThing1()
  thing2: Option[String] <- repo.queryForThing2()
  thing3: Option[String] <- repo.queryForThing3()
  thing4: Option[String] <- repo.queryForThing4()
  thing5: Option[String] <- repo.queryForThing5()
  thing6: Option[String] <- repo.queryForThing6()
  thing7: Option[String] <- repo.queryForThing7()
} yield (thing1, thing2, thing3, thing4, thing5, thing6, thing7) match {
  case (a, b, c, c, d, e, f) => ( 
    a.getOrElse("default"),
    b.getOrElse("default"),
    c.getOrElse("default"),
    c.getOrElse("default"),
    d.getOrElse("default"),
    e.getOrElse("default"),
    f.getOrElse("default")
  )
}

答案 1 :(得分:0)

由于MyOtherType采用一个序列,因此您可以创建一个查询序列并将其映射到结果:

Future.sequence(List(
  repo.queryForThing1().map(_.getOrElse(MyType("1", 1, 7))),
  repo.queryForThing2().map(_.getOrElse(MyType("2", 2, 6))),
  repo.queryForThing3().map(_.getOrElse(MyType("3", 3, 5))),
  repo.queryForThing4().map(_.getOrElse(MyType("4", 4, 4))),
  repo.queryForThing5().map(_.getOrElse(MyType("5", 5, 3))),
  repo.queryForThing6().map(_.getOrElse(MyType("6", 6, 2))),
  repo.queryForThing7().map(_.getOrElse(MyType("7", 7, 1)))
)).map(MyOtherType)

但是,这与原始代码的不同之处在于它同时执行所有查询,而不是顺序执行,并且如果其中一个查询失败,它不会提早停止。

事实上,您有七个不同的查询和七个不同的默认值,这意味着您将不得不将它们分别写出,因此看起来总是有些混乱。


作为参考,这是一个可以串行而不是并行执行查询的版本,但这并不漂亮!

val queries =
  List(
    repo.queryForThing1 _ -> MyType("1", 1, 7),
    repo.queryForThing2 _ -> MyType("2", 2, 6),
    repo.queryForThing3 _ -> MyType("3", 3, 5),
    repo.queryForThing4 _ -> MyType("4", 4, 4),
    repo.queryForThing5 _ -> MyType("5", 5, 3),
    repo.queryForThing6 _ -> MyType("6", 6, 2),
    repo.queryForThing7 _ -> MyType("7", 7, 1)
  )

queries.foldLeft(Future.successful(Vector.empty[MyType])) {
  case (prev, (query, default)) =>
    prev.flatMap(p => query().map(q => p :+ q.getOrElse(default)))
}.map(MyOtherType)