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

如何将其中一个值的列表转换为正确值的列表?

张浩阔
2023-03-14

我对字符串列表进行了一些数据转换,得到了一个列表,其中左表示错误,右表示成功转换的项。

val results: Seq[Either[String, T]] = ... 

我将结果划分为:

val (errors, items) = results.partition(_.isLeft)

做了一些错误处理后,我想返回有效项目的Seq[T]。这意味着,返回所有右元素的值。由于分区,我已经知道项目right的所有元素。我想出了五种可能的方法。但是易读性和性能最好的是什么?在Scala中有没有惯用的方法

// which variant is most scala like and still understandable?
items.map(_.right.get)
items.map(_.right.getOrElse(null))
items.map(_.asInstanceOf[Right[String, T]].value)
items.flatMap(_.toOption)
items.collect{case Right(item) => item}

共有3个答案

章稳
2023-03-14

逐一检查:

items.map(_.right.get)

你已经知道这些都是权利。这绝对没问题。

items.map(_.right.getOrElse(null))

<代码>。这里不需要getOrElse,因为您已经知道它永远不会发生。我建议,如果您(不知何故)发现一个左项,则抛出一个异常,类似这样:项。地图(x=

items.map(_.asInstanceOf[Right[String, T]].value)

这是不必要的复杂。我也无法编译这个,但我可能做错了什么。无论哪种方式,都不需要在此处使用安装。

items.flatMap(_.toOption)

我也无法编译这个<代码>项目。flatMap(\uu.right.toooption)为我编译,但在那一点上,它将始终是一个Some,您仍然需要。获取它。

items.collect{case Right(item) => item}

这是另一个“它起作用了,但为什么这么复杂?”。如果有一个左边的项目,它也不是详尽的,但是这种情况永远不会发生,所以没有必要使用。收集

另一种获取正确值的方法是模式匹配:

items.map {
  case Right(value) => value
  case other => throw new Exception(s"Unexpected Left: $other")
}

但是,这可能是不必要的,因为你已经知道所有的值都是正确的。

如果您要像这样对结果进行分区,我推荐第一个选项,items.map(_.right.get)。任何其他选项要么有无法访问的代码(您永远无法通过单元测试或实际操作访问的代码),要么为了“看起来实用”而不必要地复杂。

端木志诚
2023-03-14

从Scala 2.13开始,您可能更喜欢分区图(partitionMap)而不是分区(partition)。

它基于返回的函数对元素进行分区。在您的情况下,这只是标识

val (lefts, rights) = List(Right(1), Left("2"), Left("3")).partitionMap(identity)
// val lefts:  List[String] = List(2, 3)
// val rights: List[Int]    = List(1)

它允许您独立使用lefts和rights,并使用正确的类型。

沈运恒
2023-03-14

使用. get被认为是“代码气味”:在这种情况下它会起作用,但会让代码的读者暂停并花费一些额外的“周期”来“证明”它是可以的。最好避免在上使用. get之类的东西无论是Option还是。在MapIndexedSeq上应用

<代码>。getOrElse正常。。。但是,在scala代码中,您并不经常看到null。再次,让读者停下来思考“为什么会出现这种情况?如果它最终返回null会发生什么?”等等。最好避免。

. asInstanceOf是...很糟糕。它破坏了类型安全,只是...不scala。

剩下的就是<代码>。平面图(\uu.t选项)或。收集。两者都很好。我个人更喜欢后者,因为它更明确(并且不会让读者停下来记住哪种方式是有偏见的)。

您还可以使用foldRight一次完成分区和提取:

 val (errors, items) = results.foldRight[(List[String], List[T])](Nil,Nil) { 
    case (Left(error), (e, i)) => (error :: e, i)
    case ((Right(result), (e, i)) => (e, result :: i)
 }
 类似资料:
  • 问题内容: 嗨,我有一个这样的数据框: 我想将其更改为: 我怎样才能做到这一点? 问题答案: 您可以这样操作:

  • 问题内容: 可以说我在PostgreSQL中有一个带有以下各列的表: 我插入了这两行: 我想将上面的行转换为此(在PostgreSQL中进行选择): 调用PHP 并得到这样的东西: 但是现在,如果我用php调用,我会得到: 希望有人能帮助我解决这个问题,谢谢大家 问题答案: 在9.4中很简单(使用了LATERAL join和jsonb函数): 确切结果:

  • 问题内容: 我有一个包含两列的表: 我需要在PostgreSQL中进行某种形式的一键编码并将表转换为: 是否可以仅使用SQL?有关如何入门的任何提示? 问题答案: 如果我正确理解,则需要条件聚合:

  • 我正在尝试将列表的元组转换为列表,但是我没有成功,所以我有了这个函数 获取输入,例如: ( [1,2,3,4], [7,8,9] ) 并应返回: [1,7,2,8,3,9,4] 我有 结果是: [1,7,2,8,3,9***异常:hw2.hs:29: 1-54:函数函数中的非穷尽模式 我知道我得到这个错误,因为列表是不一样的大小,你们怎么认为我可以解决这个问题

  • 大家好,我有一个数据集,看起来像下面的df1,我想让它看起来像使用熊猫的df2。我曾经尝试过使用枢轴和转置,但我不知道该怎么做。谢谢你的帮助!

  • 我有一个类似下面的系列, 我想根据list(explode)中的值将此单个系列转换为dataframe。 预期产出: 我试过了 我上面的代码可以完成这项工作,尽管我正在寻找解决这个问题的好方法。