gpt4 book ai didi

scala - 发生错误时使用失败来破坏集合的 `find` 方法的惯用 Scala 方法是什么?

转载 作者:行者123 更新时间:2023-12-05 00:09:50 24 4
gpt4 key购买 nike

def findUseById(userId: Long, usersJson: Seq[JsObject]): Try[Option[JsObject]] = {
usersJson.find { userJson =>
(userJson \ "id").validate[Long] {
case Right(uid) => uid == userId
case Left(error) =>
// How to break find loop and "map" it to failure
// (like Failure(new SomeException())) ?
}
}
}

打破查找循环并将其映射到失败的惯用方法是什么?
  • 我想避免使用异常(抛出异常并将其包装到 Try() 中)
  • 我想避免使用 return
  • 这应该或多或少具有性能(所以我相信递归不起作用,也不会折叠,因为它会扫描集合到最后)。
  • 最佳答案

    这是该问题的一个简单、高效且实用的解决方案。
    它利用了迭代器 懒惰和collectFirst早点回来。

    import scala.util.{Failure, Success, Try}

    def validateAndFind[A, B](data: Seq[A], target: B)
    (validationFun: A => Either[Throwable, (A, B)]): Try[Option[A]] =
    data
    .iterator
    .map(validationFun)
    .collectFirst {
    case Right((elem, value)) if (value == target) => Right(elem)
    case Left(ex) => Left(ex)
    } match {
    case None => Success(None)
    case Some(Right(elem)) => Success(Some(elem))
    case Some(Left(ex)) => Failure(ex)
    }

    但是,我不确定是否是 试试 选项 是最好的类型。
    例如,您可以删除最后的匹配项并返回 选项 试试 相反,或者仅对未找到的值使用自定义异常呢?
    sealed trait ValidationError extends Product with Serializable
    final case object ElementNotFound extends ValidationError
    final case class ValidationFailure(cause: Throwable) extends ValidationError

    def validateAndFind[A, B](data: Seq[A], target: B)
    (validationFun: A => Either[Throwable, (A, B)]): Either[ValidationError, A] =
    data
    .iterator
    .map(validationFun)
    .collectFirst {
    case Right((elem, value)) if (value == target) => Right(elem)
    case Left(ex) => Left(ValidationFailure(cause = ex))
    }.getOrElse(Left(ElementNotFound))

    无论如何,这两个代码是等效的并且按预期工作:
    final case class User(name: String, age: Int)

    validateAndFind(
    data = List(
    User(name = "Balmung", age = 22),
    User(name = "Luis", age = 22),
    User(name = "Miguel", age = 22)
    ),
    target = "Luis"
    ) { user =>
    println(s"Validating user: ${user}")
    if (user.age < 18) Left(new IllegalArgumentException("User underage"))
    else Right(user -> user.name)
    }

    // Validating user: User(Balmung,22)
    // Validating user: User(Luis,22)
    // res: Either[ValidationError, User] = Right(User("Luis", 22))

    如您所见,它没有验证第三个元素,因为它不是必需的。
    让我们看看另外两个要求。
    validateAndFind(
    data = List(
    User(name = "Balmung", age = 16),
    User(name = "Luis", age = 22),
    User(name = "Miguel", age = 22)
    ),
    target = "Luis"
    ) { user =>
    println(s"Validating user: ${user}")
    if (user.age < 18) Left(new IllegalArgumentException("User underage"))
    else Right(user -> user.name)
    }

    // Validating user: User(Balmung,16)
    // res: Either[ValidationError, User] = Left(ValidationFailure(java.lang.IllegalArgumentException: User underage))


    validateAndFind(
    data = List(
    User(name = "Balmung", age = 22),
    User(name = "Luis", age = 22),
    User(name = "Miguel", age = 22)
    ),
    target = "Mario"
    ) { user =>
    println(s"Validating user: ${user}")
    if (user.age < 18) Left(new IllegalArgumentException("User underage"))
    else Right(user -> user.name)
    }

    // Validating user: User(Balmung,22)
    // Validating user: User(Luis,22)
    // Validating user: User(Miguel,22)
    // res: Either[ValidationError, User] = Left(ElementNotFound)

    关于scala - 发生错误时使用失败来破坏集合的 `find` 方法的惯用 Scala 方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59849770/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com