如何更好地对有效或无效输入进行分区



给定一个可能有效或无效的输入列表,是否有一种很好的方法来转换列表,但在给定一个或多个无效输入时失败,并在必要时返回有关这些无效输入的信息?我有这样的东西,但感觉很不雅。

def processInput(inputList: List[Input]): Try[List[Output]] = {
inputList map { input =>
if (isValid(input)) Left(Output(input))
else Right(input)
} partition { result =>
result.isLeft
} match {
case (valids, Nil) => 
val outputList = valids map { case Left(output) => output }
Success(outputList)
case (_, invalids) => 
val errList =  invalids map { case Right(invalid) => invalid }
Failure(new Throwable(s"The following inputs were invalid: ${errList.mkString(",")}")) 
}
}

有更好的方法吗?

我认为您可以使用标准scala:来简化当前的解决方案

def processInput(inputList: List[Input]): Try[List[Output]] = 
inputList.partition(isValid) match {
case (valids, Nil) => Success(valids.map(Output))
case (_, invalids) => Failure(new Throwable(s"The following inputs were invalid: ${invalids.mkString(",")}"))
}

或者,您可以使用scalacticOr获得一个非常优雅的解决方案。

import org.scalactic._
def processInputs(inputList: List[Input]): List[Output] Or List[Input] = 
inputList.partition(isValid) match {
case (valid, Nil) => Good(valid.map(Output))
case (_, invalid) => Bad(invalid)
}

结果的类型为org.scalactic.Or,然后必须将其与GoodBad匹配。如果你想要无效输入的列表,这种方法更有用,你可以从Bad中匹配它。

scalaz的验证正是为此而设计的。试着阅读三家夜总会的故事,了解它是如何运作的,但你的功能可能最终只由以下部分组成:

def processInput(inputList: List[Input]): Validation[List[Output]] = {
inputList foldMap { input =>
if (isValid(input)) Failure(Output(input))
else Success(List(input))
}

最新更新