Scala 如何检查是否存在';在列表[Option[#]]中设置None并返回元素';她叫什么名字?
我有多个Scala 如何检查是否存在';在列表[Option[#]]中设置None并返回元素';她叫什么名字?,scala,Scala,我有多个选项。我想检查它们是否有值。如果选项为无,我想就此回复用户。否则继续 这就是我所做的: val name:Option[String] val email:Option[String] val pass:Option[String] val i = List(name,email,pass).find(x => x match{ case None => true case _ => false }) i match{ case Some(x) =>
选项
。我想检查它们是否有值。如果选项
为无
,我想就此回复用户。否则继续
这就是我所做的:
val name:Option[String]
val email:Option[String]
val pass:Option[String]
val i = List(name,email,pass).find(x => x match{
case None => true
case _ => false
})
i match{
case Some(x) => Ok("Bad Request")
case None => {
//move forward
}
}
上面我可以用contains
替换find
,但这是一种非常肮脏的方式。我怎样才能使它优雅而独居
编辑:我还想知道什么元素是
None
我认为最简单的方法是:
val response = for {
n <- name
e <- email
p <- pass
} yield {
/* do something with n, e, p */
}
response getOrElse { /* bad request /* }
(name,email,pass) match {
case ((Some(name), Some(email), Some(pass)) => // proceed
case _ => // Bad request
}
另一种方式是作为理解的一种方式:
val outcome = for {
nm <- name
em <- email
pwd <- pass
result = doSomething(nm, em, pwd) // where def doSomething(name: String, email: String, password: String): ResultType = ???
} yield (result)
如果您想重用代码,可以这样做
def allFieldValueProvided(fields: Option[_]*): Boolean = fields.forall(_.isDefined)
如果你想知道所有缺失的值,那么你可以找到所有缺失的值,如果没有,那么你就可以走了
def findMissingValues(v: (String, Option[_])*) = v.collect {
case (name, None) => name
}
val missingValues = findMissingValues(("name1", option1), ("name2", option2), ...)
if(missingValues.isEmpty) {
Ok(...)
} else {
BadRequest("Missing values for " + missingValues.mkString(", ")))
}
带有石刀和熊皮的版本:
import util._
object Test extends App {
val zero: Either[List[Int], Tuple3[String,String,String]] = Right((null,null,null))
def verify(fields: List[Option[String]]) = {
(zero /: fields.zipWithIndex) { (acc, v) => v match {
case (Some(s), i) => acc match {
case Left(_) => acc
case Right(t) =>
val u = i match {
case 0 => t copy (_1 = s)
case 1 => t copy (_2 = s)
case 2 => t copy (_3 = s)
}
Right(u)
}
case (None, i) =>
val fails = acc match {
case Left(f) => f
case Right(_) => Nil
}
Left(i :: fails)
}
}
}
def consume(name: String, email: String, pass: String) = Console println s"$name/$email/$pass"
def fail(is: List[Int]) = is map List("name","email","pass") foreach (Console println "Missing: " + _)
val name:Option[String] = Some("Bob")
val email:Option[String]= None
val pass:Option[String] = Some("boB")
val res = verify(List(name,email,pass))
res.fold(fail, (consume _).tupled)
val res2 = verify(List(name, Some("bob@bob.org"),pass))
res2.fold(fail, (consume _).tupled)
}
同样,使用反射来泛化元组副本
缺点是您必须告诉它希望返回什么tuple。在这种形式下,反射就像是石器时代的进步之一,它是如此神奇,以至于在推特上流行了一万年
def verify[A <: Product](fields: List[Option[String]]) = {
import scala.reflect.runtime._
import universe._
val MaxTupleArity = 22
def tuple = {
require (fields.length <= MaxTupleArity)
val n = fields.length
val tupleN = typeOf[Tuple2[_,_]].typeSymbol.owner.typeSignature member TypeName(s"Tuple$n")
val init = tupleN.typeSignature member nme.CONSTRUCTOR
val ctor = currentMirror reflectClass tupleN.asClass reflectConstructor init.asMethod
val vs = Seq.fill(n)(null.asInstanceOf[String])
ctor(vs: _*).asInstanceOf[Product]
}
def zero: Either[List[Int], Product] = Right(tuple)
def nextProduct(p: Product, i: Int, s: String) = {
val im = currentMirror reflect p
val ts = im.symbol.typeSignature
val copy = (ts member TermName("copy")).asMethod
val args = copy.paramss.flatten map { x =>
val name = TermName(s"_$i")
if (x.name == name) s
else (im reflectMethod (ts member x.name).asMethod)()
}
(im reflectMethod copy)(args: _*).asInstanceOf[Product]
}
(zero /: fields.zipWithIndex) { (acc, v) => v match {
case (Some(s), i) => acc match {
case Left(_) => acc
case Right(t) => Right(nextProduct(t, i + 1, s))
}
case (None, i) =>
val fails = acc match {
case Left(f) => f
case Right(_) => Nil
}
Left(i :: fails)
}
}.asInstanceOf[Either[List[Int], A]]
}
def consume(name: String, email: String, pass: String) = Console println s"$name/$email/$pass"
def fail(is: List[Int]) = is map List("name","email","pass") foreach (Console println "Missing: " + _)
val name:Option[String] = Some("Bob")
val email:Option[String]= None
val pass:Option[String] = Some("boB")
type T3 = Tuple3[String,String,String]
val res = verify[T3](List(name,email,pass))
res.fold(fail, (consume _).tupled)
val res2 = verify[T3](List(name, Some("bob@bob.org"),pass))
res2.fold(fail, (consume _).tupled)
def验证[A/v匹配{
案例(部分,i)=>acc匹配{
案例左侧()=>acc
案例右侧(t)=>右侧(下一个产品(t,i+1,s))
}
案例(无,i)=>
val失败=acc匹配{
案例左侧(f)=>f
右格()=>Nil
}
左(i::失败)
}
}.asInstanceOf[List[Int],A]]
}
def消费(名称:String,电子邮件:String,传递:String)=控制台打印LN s“$name/$email/$pass”
def fail(is:List[Int])=is映射列表(“名称”、“电子邮件”、“通过”)foreach(控制台println“缺失:”+41;
val名称:选项[String]=Some(“Bob”)
val电子邮件:选项[字符串]=无
val pass:Option[String]=Some(“boB”)
类型T3=Tuple3[字符串,字符串,字符串]
val res=验证[T3](列表(姓名、电子邮件、通行证))
res.fold(失败,(消耗)元组)
val res2=验证[T3](列表(名称,部分)bob@bob.org(通过)
res2.折叠(失败,(消耗)。折叠)
我知道这不能很好地扩展,但这就足够了吗
(name, email, pass) match {
case (None, _, _) => "name"
case (_, None, _) => "email"
case (_, _, None) => "pass"
case _ => "Nothing to see here"
}
如果(list.exists(u.isEmpty))确定(“错误请求”),否则{…}“我有多个选项。”总是有选择的。有任何方法可以使用scala内置来实现吗api@Jatin我已经用一个仅使用标准库的示例更新了我的答案。问题是:我不想做
doSomething
是之前的任何一个None@Jatin这就是for comprehension的工作原理-如果任何值为None,则构造将(实际上)中止(不产生任何元素)和doSomething将不会被调用。您可以将其视为对三个列表进行迭代,每个列表包含零个或一个元素。如果每个列表都有一个元素,则会发生最终执行,如果任何列表有零个元素,则不会发生“内部”迭代或执行。
def findMissingValues(v: (String, Option[_])*) = v.collect {
case (name, None) => name
}
val missingValues = findMissingValues(("name1", option1), ("name2", option2), ...)
if(missingValues.isEmpty) {
Ok(...)
} else {
BadRequest("Missing values for " + missingValues.mkString(", ")))
}
import util._
object Test extends App {
val zero: Either[List[Int], Tuple3[String,String,String]] = Right((null,null,null))
def verify(fields: List[Option[String]]) = {
(zero /: fields.zipWithIndex) { (acc, v) => v match {
case (Some(s), i) => acc match {
case Left(_) => acc
case Right(t) =>
val u = i match {
case 0 => t copy (_1 = s)
case 1 => t copy (_2 = s)
case 2 => t copy (_3 = s)
}
Right(u)
}
case (None, i) =>
val fails = acc match {
case Left(f) => f
case Right(_) => Nil
}
Left(i :: fails)
}
}
}
def consume(name: String, email: String, pass: String) = Console println s"$name/$email/$pass"
def fail(is: List[Int]) = is map List("name","email","pass") foreach (Console println "Missing: " + _)
val name:Option[String] = Some("Bob")
val email:Option[String]= None
val pass:Option[String] = Some("boB")
val res = verify(List(name,email,pass))
res.fold(fail, (consume _).tupled)
val res2 = verify(List(name, Some("bob@bob.org"),pass))
res2.fold(fail, (consume _).tupled)
}
def verify[A <: Product](fields: List[Option[String]]) = {
import scala.reflect.runtime._
import universe._
val MaxTupleArity = 22
def tuple = {
require (fields.length <= MaxTupleArity)
val n = fields.length
val tupleN = typeOf[Tuple2[_,_]].typeSymbol.owner.typeSignature member TypeName(s"Tuple$n")
val init = tupleN.typeSignature member nme.CONSTRUCTOR
val ctor = currentMirror reflectClass tupleN.asClass reflectConstructor init.asMethod
val vs = Seq.fill(n)(null.asInstanceOf[String])
ctor(vs: _*).asInstanceOf[Product]
}
def zero: Either[List[Int], Product] = Right(tuple)
def nextProduct(p: Product, i: Int, s: String) = {
val im = currentMirror reflect p
val ts = im.symbol.typeSignature
val copy = (ts member TermName("copy")).asMethod
val args = copy.paramss.flatten map { x =>
val name = TermName(s"_$i")
if (x.name == name) s
else (im reflectMethod (ts member x.name).asMethod)()
}
(im reflectMethod copy)(args: _*).asInstanceOf[Product]
}
(zero /: fields.zipWithIndex) { (acc, v) => v match {
case (Some(s), i) => acc match {
case Left(_) => acc
case Right(t) => Right(nextProduct(t, i + 1, s))
}
case (None, i) =>
val fails = acc match {
case Left(f) => f
case Right(_) => Nil
}
Left(i :: fails)
}
}.asInstanceOf[Either[List[Int], A]]
}
def consume(name: String, email: String, pass: String) = Console println s"$name/$email/$pass"
def fail(is: List[Int]) = is map List("name","email","pass") foreach (Console println "Missing: " + _)
val name:Option[String] = Some("Bob")
val email:Option[String]= None
val pass:Option[String] = Some("boB")
type T3 = Tuple3[String,String,String]
val res = verify[T3](List(name,email,pass))
res.fold(fail, (consume _).tupled)
val res2 = verify[T3](List(name, Some("bob@bob.org"),pass))
res2.fold(fail, (consume _).tupled)
(name, email, pass) match {
case (None, _, _) => "name"
case (_, None, _) => "email"
case (_, _, None) => "pass"
case _ => "Nothing to see here"
}