简体   繁体   English

如何在理解中对多个事物进行模式匹配

[英]How to pattern match on multiple things in a for comprehension

I have a for comprehension that has 7 things inside it. 我有一个理解,里面有7件事。 The 7 things are running DB queries in Slick and might not return any data. 7东西在Slick中运行数据库查询,可能不会返回任何数据。 When they don't return any data, I want default values put it. 当他们不返回任何数据时,我想要默认值。 I can do the following if there was only 1 thing but how do I do this when I have 7 ? 如果只有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)))
  }
}

Question

How can I pattern match for 7 things? 我怎样才能匹配7件事? Each one will have default value of thing<number> when it is None 当它为None时,每个都具有thing<number>默认值

Try this! 尝试这个! but this is not a sexy code :D 但这不是一个性感的代码: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")
  )
}

Since MyOtherType takes a sequence you could create a sequence of queries and map that to the result: 由于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)

However this is different from the original code in that it performs all the queries at the same time rather than sequentially, and won't stop early if one of the queries fails. 然而,这与原始代码的不同之处在于它同时执行所有查询而不是顺序执行,并且如果其中一个查询失败,则不会提前停止。

The fact that you have seven different queries and seven different defaults means that you are going to have to write them out individually so it is always going to look a little messy. 事实上,您有七个不同的查询和七个不同的默认值意味着您将不得不单独编写它们,因此它总是看起来有点混乱。


For reference, here is a version that performs the queries in series rather than in parallel, but it isn't pretty! 作为参考,这里是一个版本,它以串行而不是并行的方式执行查询,但它并不漂亮!

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM