当前位置: 首页 > 知识库问答 >
问题:

如何从元组中收集一个或的左边?

杨轶
2023-03-14

在对一堆类型为[String, A](其中A是多种类型)的Eithers进行匹配后,我想将左侧的任何字符串累积到一个列表中。

(a, b, c, d, e) match {
  case (Right(a), Right(b), Right(c), Right(d), Right(e)) => {
    "All good, use a, b, c, d, and e!"
  }
  case anythingElse => {
    val strings = accLefts(anythingElse)
    doSomethingWithStrings(strings)
  }
}

如果我尝试. productIterator.toList元组,我最终会得到List[any]。如果我单独处理每个失败的案例(权利和左的组合),我最终会得到指数数量的案例语句。

我怎样才能在最后得到一个列表[[字符串,任何]]来传递给我的加注?或者我应该做些什么而不是比赛?

共有3个答案

董子平
2023-03-14

我可能会创建一组实用函数,如

def fromTuple2[A, That](t: Tuple2[A,A])(implicit bf : CanBuildFrom[Nothing, A, That]): That =
  (bf.apply() += (t._1, t._2)).result();

对于您需要的所有n元组。虽然有很多样板代码,但这只是一次性工作。然后您可以执行以下操作:

val e1: Either[String,Int] = Right(3);
val e2: Either[String,String] = Left("3");
val test: List[Either[String,Any]] = fromTuple2(e1, e2);

也许更好的是,我们可以使用丰富的隐式方法,例如

implicit def fromTuple2Impl[A](t: Tuple2[A,A]) = new {
  def asCollection[That](implicit bf : CanBuildFrom[Nothing, A, That]): That =
    (bf.apply() += (t._1, t._2)).result();
}

只写

val test: List[Either[String,Any]] = (e1, e2).asCollection;

编辑:我们甚至可以将元组丰富为可遍历的元组,这为我们提供了所有方法,如toList、folding等:

implicit def fromTuple2Impl3[A](t: Tuple2[A,A]) = new Traversable[A] {
  def asCollection[That](implicit bf : CanBuildFrom[Nothing, A, That]): That =
    (bf.apply() += (t._1, t._2)).result();
  override def foreach[U](f: (A) => U): Unit = {
    f(t._1); f(t._2);
  }
}

通过进一步的工作,我们可以进一步实现IndexedSeq。

冀俊良
2023-03-14

也许与嵌套模式匹配?

case anythingElse => {
    val strings = anythingElse
                    .productIterator
                    .collect { case Left(str: String) => str }
                    .toList
    doSomethingWithStrings(strings)
}

请注意,这里的str: String是为了指导类型推断,因此字符串的类型为List[String]而不是List[Any]

洪研
2023-03-14

这正是Scalaz中的ValidationNEL(本质上是一个增强版)设计用来支持的东西。例如,假设我们使用Scalaz 7进行以下设置:

import scalaz._, Scalaz._

case class Person(first: String, last: String, initial: Char, age: Int)

val first = "John".successNel[String]

val last = "Doe".successNel[String]
val badLast = "Empty last name".failureNel[String]

val initial = 'H'.successNel[String]
val badInitial = "Non-alphabetic MI".failureNel[Char]

val age = 45.successNel[String]
val badAge = "Negative age provided".failureNel[Int]

请注意,此处的Nel表示非空列表,并且表示“John”。successNel[字符串]或多或少等同于右(“John”):或者[列表[字符串],[字符串]等等。

现在我们可以写以下内容:

scala> println((first |@| last |@| initial |@| age)(Person.apply))
Success(Person(John,Doe,H,45))

或:

scala> println((first |@| badLast |@| initial |@| badAge)(Person.apply))
Failure(NonEmptyList(Empty last name, Negative age provided))

或:

scala> println((first |@| badLast |@| badInitial |@| badAge)(Person.apply))
Failure(NonEmptyList(Empty last name, Non-alphabetic MI, Negative age provided))

任何错误都累积在ValidationNEL的左侧。有关更多详细信息,请参阅例如我在此处的答案。

 类似资料:
  • 给定下面的代码: HTML: 断续器 我必须使用此代码才能删除元素吗?它似乎太冗长了。

  • 假设我的配置单元表包含以下值: 我正在使用。我在collect_list/collect_set或group_concat查询后出现此错误。 错误:org。阿帕奇。蜂箱服务cli。HiveSQLException:处理语句时出错:失败:执行错误,从组织返回代码2。阿帕奇。hadoop。蜂箱ql.exec。org的MapRedTask先生。阿帕奇。蜂箱服务cli。活动活动toSQLException

  • 我有这样的数据(地图列表): 因此,我想按“名称”对这些数据进行分组,但也要创建一个新字段,它将“源”和“状态”字段收集到对象列表中。这意味着我还必须将内部数据映射到一个Java类(将这些单独的对象称为“SourceStatus”,我已经为其创建了一个类)。 我知道groupingBy部分可以用Java的收集器(https://www.baeldung.com/java-groupingby-co

  • 问题内容: 我想了解 从另一个数组的所有元素过滤数组 的最佳方法。我尝试使用过滤器功能,但是如何给它提供要删除的值并没有解决。 就像是: 如果过滤器功能没有用,您将如何实现呢? 编辑:我检查了可能重复的问题,它可能对那些容易理解javascript的人有用。选中的答案很容易。 问题答案: 您可以使用函数的参数来避免将过滤器数组存储在全局变量中。

  • 我想了解从另一个数组的所有元素中筛选一个数组的最佳方法。我尝试了筛选函数,但我不知道如何给它我想要删除的值。 类似内容: 如果过滤器功能不是有用的,你将如何实现它? 编辑:我检查了可能重复的问题,对于那些容易理解javascript的人来说,它可能很有用。如果答案被检查为好,事情就会变得简单。

  • 问题内容: 我想知道是否可以获取列表或集合的第一个元素。使用哪种方法? 问题答案: Collection c; (这是获得a的“第一个”元素的最接近的位置。您应该意识到,它对于的大多数实现绝对没有任何意义。这可能对LinkedHashSet和TreeSet有意义,但对HashSet没有意义。)