Scala Case 类的更新操作

2024-04-19

我有两个相同类型的实例化案例类。

case class Foo(x : Option[String], y : Option[String], z : Option[String])

让我们调用实例化的类 A 和 B。

val a = Foo(x=Some("foo"), y=Some("bar"), z=Some("baz"))
val b = Foo(x=None, y=Some("etch"), z=None)

我想知道是否可以以通用方式在单个操作中用 B 更新案例类 A。

val c = b *oper* a // produces Foo(x=Some("foo"), y=Some("etch"), z=Some("baz")) 

参数设置为 None 被忽略。理想情况下,该操作也应该是通用的,以便它可以作用于任何类型的案例类。

我有一些直觉,可以通过首先将类转换为元组/列表并在操作完成后转换回类来使用 Scalaz 来完成此操作 - 也许使用 ApplicativeBuilder?我是否以正确的方式思考这个问题?有任何想法吗?


相当简单的 Scalaz 解决方案(不是很通用)

您可以使用半组实例来包装许多细节:

import scalaz._, Scalaz._

case class Foo(a: Option[String], b: Option[String], c: Option[String])

implicit object fooSemigroup extends Semigroup[Foo] {
  def fromFoo(f: Foo) = (f.a.fst, f.b.fst, f.c.fst)
  def toFoo(t: (FirstOption[String], FirstOption[String], FirstOption[String])) =
    Foo(t._1.value, t._2.value, t._3.value)
  def append(x: Foo, y: => Foo) = toFoo(fromFoo(x) |+| fromFoo(y))
}

这给了我们:

scala> val a = Foo(Some("foo"), Some("bar"), Some("baz"))
a: Foo = Foo(Some(foo),Some(bar),Some(baz))

scala> val b = Foo(None, Some("etch"), None)
b: Foo = Foo(None,Some(etch),None)

scala> b |+| a
res11: Foo = Foo(Some(foo),Some(etch),Some(baz))

我认为这就是你想要的,尽管它不是很普遍。


Scalaz + Shapeless 解决方案

如果您想要适用于所有案例类的东西(给定成员的适当类型类实例),您可以使用以下组合无形的 https://github.com/milessabin/shapeless/和斯卡拉兹。请注意,我正在绘制缺失因素的答案 https://stackoverflow.com/a/11446109/334519 and 这个例子 https://github.com/milessabin/shapeless/blob/master/examples/src/main/scala/shapeless/examples/monoids.scala作者:迈尔斯·萨宾。首先对于一些幺半群实例:

import scalaz._, Scalaz._
import shapeless._, HList._

implicit object hnilMonoid extends Monoid[HNil] {
  val zero = HNil
  def append(a: HNil, b: => HNil) = HNil
}

implicit def hlistMonoid[H, T <: HList](
  implicit mh: Monoid[H],
  mt: Monoid[T]
): Monoid[H :: T] = new Monoid[H :: T] {
  val zero = mh.zero :: mt.zero
  def append(a: H :: T, b: => H :: T) =
    (a.head |+| b.head) :: (a.tail |+| b.tail)
}

implicit def caseClassMonoid[C, L <: HList](
  implicit iso: Iso[C, L],
  ml: Monoid[L]
) = new Monoid[C] {
  val zero = iso.from(ml.zero)
  def append(a: C, b: => C) = iso.from(iso.to(a) |+| iso.to(b))
}

接下来,为了简单起见,我将把“第一个”幺半群实例放在Option在范围内,而不是使用FirstOption包装就像我上面做的那样。

implicit def optionFirstMonoid[A] = new Monoid[Option[A]] {
  val zero = None
  def append(a: Option[A], b: => Option[A]) = a orElse b
}

现在我们的案例类:

case class Foo(a: Option[String], b: Option[String], c: Option[String])

And the Iso实例将其转换为HList然后回来:

implicit def fooIso = Iso.hlist(Foo.apply _, Foo.unapply _)

我们就完成了:

scala> val a = Foo(Some("foo"), Some("bar"), Some("baz"))
a: Foo = Foo(Some(foo),Some(bar),Some(baz))

scala> val b = Foo(None, Some("etch"), None)
b: Foo = Foo(None,Some(etch),None)

scala> b |+| a
res0: Foo = Foo(Some(foo),Some(etch),Some(baz))

您也可以在这里使用半群而不是幺半群并节省几行,但我试图摆脱尽可能多的复制和粘贴shapeless/examples尽可能编写代码,所以我将其作为练习。


表现

为了解决您对性能的评论,这是后一种解决方案与使用标准库解决方案的完全不科学的基准orElse(Scala 2.9.2、IcedTea7 2.2.1):

def add(x: Foo, y: Foo) = Foo(x.a orElse y.a, x.b orElse y.b, x.c orElse y.c)

def ros = if (util.Random.nextBoolean)
  Some(util.Random.nextString(util.Random.nextInt(10))) else None

val foos = Seq.fill(500000)(Foo(ros, ros, ros))

def time(block: => Unit) = {
  val start = System.currentTimeMillis
  (block, System.currentTimeMillis - start)
}

然后每个运行几十次后:

scala> Iterator.fill(10)(time(foos.reduce(add(_, _)))._2).sum / 10
res4: Long = 49

scala> Iterator.fill(10)(time(foos.reduce(_ |+| _))._2).sum / 10
res5: Long = 265

有点令人惊讶的是,Shapeless-less Scalaz 解决方案有点慢:

scala> Iterator.fill(10)(time(foos.reduce(_.|+|(_)(fooSemigroup)))._2).sum / 10
res6: Long = 311

但正如我所说,这是一种非常即兴的基准测试方法,您应该运行自己的(Caliper http://code.google.com/p/caliper/是一个很棒的库)。

无论如何,是的,您为抽象付出了代价,但不是那么多,而且通常是值得的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Scala Case 类的更新操作 的相关文章

  • 用惯用的 Scala 更新大型数据结构

    我已经尝试 Scala 一段时间了 并且经常遇到支持不可变数据结构的建议 但是当你有一个像这样的数据结构时3D 场景图 大型神经网络或任何具有大量需要频繁更新的对象的东西 对场景中的对象进行动画处理 训练神经网络 这似乎是 运行时效率极低
  • Scala REPL 中的递归重载语义 - JVM 语言

    使用 Scala 的命令行 REPL def foo x Int Unit def foo x String Unit println foo 2 gives error type mismatch found Int 2 required
  • 如何从字符串列中提取数字?

    我的要求是从列中的评论列中检索订单号comment并且总是开始于R 订单号应作为新列添加到表中 输入数据 code id mode location status comment AS SD 101 Airways hyderabad D
  • Scala(或 Java)中泛型函数的特化

    是否可以在 Scala 中专门化泛型函数 或类 例如 我想编写一个将数据写入 ByteBuffer 的通用函数 def writeData T buffer ByteBuffer data T buffer put data 但由于 put
  • 在 Akka 中配置嵌套 Router

    我有一些嵌套的路由器 应创建它FromConfig 我想要的是这样的 test akka actor deployment worker router round robin nr of instances 5 slave router b
  • 如何将模型结果保存到文本文件?

    我正在尝试将从模型生成的频繁项集保存到文本文件中 该代码是 Spark ML 库中 FPGrowth 示例的示例 Using saveAsTextFile直接在模型上写入 RDD 位置而不是实际值 import org apache spa
  • 如何在 Apache Spark 中通过 DStream 使用特征提取

    我有通过 DStream 从 Kafka 到达的数据 我想进行特征提取以获得一些关键词 我不想等待所有数据的到达 因为它是可能永远不会结束的连续流 所以我希望以块的形式执行提取 如果准确性会受到一点影响 对我来说并不重要 到目前为止 我整理
  • 多个 scala 库导致 intellij 出错?

    我正在使用 intellij 14 和 scala 2 11 6 使用 homebrew 安装并使用符号链接 ln s usr local Cellar scala 2 11 6 libexec src usr local Cellar s
  • 如何从命令行向 REPL 添加导入?

    如何使 REPL 导入命令行中给出的包 Sample scala someMagicHere import sys error scala gt imports 1 import scala Predef 162 terms 78 are
  • Spark SQL 失败,因为“常量池已超过 JVM 限制 0xFFFF”

    我在 EMR 4 6 0 Spark 1 6 1 上运行此代码 val sqlContext SQLContext getOrCreate sc val inputRDD sqlContext read json input try inp
  • 对两种类型之间的二元关系进行建模

    有企业 也有人 用户可以对某个企业点赞或发表评论 但效果是一样的can not发生在一个人身上 当用户发布有关某个企业的内容或对其点赞时 该企业就被称为target喜欢或帖子 trait TargetingRelation Targetin
  • 具有上限的联合类型

    我正在遵循这个问题的公认答案中提出的技术如何定义 类型析取 联合类型 https stackoverflow com questions 3508077 does scala have type disjunction union type
  • 规范化且不可变的数据模型

    Haskell如何解决 规范化不可变数据结构 问题 例如 让我们考虑一个表示前女友 男友的数据结构 data Man Man name String exes Woman data Woman Woman name String exes
  • Slick和bonecp:org.postgresql.util.PSQLException:FATAL:抱歉,太多客户端已经错误

    当我在本地开发应用程序时 我使用以下命令启动我的 play2 应用程序sbt run 我喜欢如何更改代码 然后重新加载浏览器以查看我的更改 在大约 10 次代码更改之后 我收到 postgresql 太多连接错误 见下文 我的数据库连接使用
  • 在 Spark 结构化流 2.3.0 中连接两个流时,左外连接不发出空值

    两个流上的左外连接不发出空输出 它只是等待记录添加到另一个流中 使用套接字流来测试这一点 在我们的例子中 我们想要发出具有 null 值的记录 这些记录与 id 不匹配或 且不属于时间范围条件 水印和间隔的详细信息如下 val ds1Map
  • Scala 使用的 Redis 客户端库建议

    我正在计划使用 Scala 中的 Redis 实例进行一些工作 并正在寻找有关使用哪些客户端库的建议 理想情况下 如果存在一个好的库 我希望有一个为 Scala 而不是 Java 设计的库 但如果现在这是更好的方法 那么仅使用 Java 客
  • Java 拥有闭包后 Scala 的优势 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 随着 Java 中添加了闭包 作为语言选择 Scala 相对于 Java 的优势是什么 有人可以详细说明一下有什么优点吗 除了闭包 J
  • Scala:类型参数中的问号

    我试图理解以下代码 来自 Scalaz 库 def kleisliIdApplicative R Applicative Kleisli Id R 我假设一种形式T P0 是一个带有参数的类型构造函数 但是我无法找到解释类型参数中问号用法的
  • 如何在不从 DataFrame 转换并访问它的情况下向数据集添加列?

    我知道使用以下方法将新列添加到 Spark 数据集的方法 withColumn and a UDF 它返回一个 DataFrame 我还知道 我们可以将生成的 DataFrame 转换为 DataSet 我的问题是 如果我们仍然遵循传统的
  • 在spark-kafka中使用schema将ConsumerRecord值转换为Dataframe

    我正在使用 Spark 2 0 2 和 Kafka 0 11 0 并且 我正在尝试在火花流中使用来自卡夫卡的消息 以下是代码 val topics notes val kafkaParams Map String Object bootst

随机推荐

  • 尝试理解 Pytorch 的 LSTM 实现

    我有一个包含 1000 个示例的数据集 其中每个示例都有5特征 a b c d e 我想喂7LSTM 的示例 以便它预测第 8 天的特征 a 阅读 nn LSTM 的 Pytorchs 文档 我得出以下结论 input size 5 hid
  • Akka 通过可堆叠行为拦截接收

    Akka 和 Scala 新手 请根据需要随意编辑问题 以便清楚地表达我在 Scala 和 Akka 领域的意图 在展示代码片段之前 这是我想要解决的问题 我本质上想开发一个通用模块 供我的团队在使用 Akka Actor 开发应用程序时使
  • Tcl正则表达式

    set d aa1 1 set d aa2 1 set d aa3 1 set d aa4 1 set d aa5 1 set d aa6 1 set d aa7 1 set d aa8 1 set d aa9 1 set d aa10 1
  • Fortran 读取混合文本和数字

    我正在使用 Fortran 90 读取包含以下格式数据的文件 number 125 var1 2 var2 1 var3 4 number 234 var1 3 var2 5 var3 1 我尝试了以下命令并且工作正常 read 2 tem
  • Ionic Jasmine:env.stopOnSpecFailure 编译成功后不是函数

    将 Ionic 与 jasmine karma 一起使用 在运行测试时 编译成功 但在 jasmine 仪表板中出现空屏幕 控制台中出现错误 以下教程 https leifwells github io 2017 08 27 testing
  • 受范数不等式约束的二次函数最小化

    我正在尝试解决以下不等式约束 给定 N 只股票的时间序列数据 我试图构建一个投资组合权重向量以最小化回报的方差 目标函数 min w T sum w s t e n T w 1 left w right leq C where w是权重向量
  • 从外部访问 Google 地图

    我有一些 javascript 代码 可以绘制 v3 GoogleMap 我想从外部访问地图对象 另一个js文件 是否有可能不创建额外的全局变量来引用地图 单独的 JS 文件在同一范围内加载和执行 因此无论您使用一个还是多个 JS 文件 都
  • 将参数从 tasklet 步骤添加到作业上下文,并在 Spring Batch 的后续步骤中使用

    目前 我使用 jobParameters 来获取 FlatFileItemReader 和 FlatFileItemWriter 的文件名 测试我的批次是可以的 但我的目标是读取某个目录中的文件 该目录中只有这个文件 并且文件名可能会改变
  • 错误:invalid_request 缺少必需参数:范围(Restify 和 Passportjs w/ Google OAuth2)

    因此 我在使用 Restify 和 Passportjs Google OAuth2 策略 时遇到了 Node js 应用程序的问题 当我使用passport authenticate 它给了我以下错误 400 这是一个错误 错误 无效 请
  • 提高Python代码的速度

    我有一些包含许多类的 python 代码 我用了cProfile发现程序运行总时间为68秒 我发现一个类中有以下函数Buyers这 68 秒中大约需要 60 秒 我必须运行该程序大约 100 次 因此速度的任何提高都会有所帮助 您能建议通过
  • 如何查找 C++ 中的内存泄漏

    在嵌入式环境中检测 C 内存泄漏的好方法是什么 我尝试重载 new 运算符来记录每个数据分配 但我一定做错了什么 这种方法不起作用 还有其他人遇到过类似的情况吗 这是 new 和 delete 运算符重载的代码 EDIT 完全披露 我正在寻
  • 带有大标题的导航栏 iOS 11 的图像

    AppStore app has an icon with an image on the right side of the NabBar with Large Title 如果有人的话我真的很感激知道如何实施 it or ideas关于
  • 从 FlowDocument 创建 XPS 文档并即时附加它

    我有一个 FlowDocument 我想将其转换为 XPS 文档并将其附加到电子邮件中并一起发送 我正在使用这个代码 public static Stream FlowDocumentToXPS FlowDocument flowDocum
  • 使用 Java 应用程序运行 Orbeon-Form-Builder-Generate-Form

    我应该能够使用 Java 应用程序运行 Orbeon Form Builder Generated Form 吗 即 将表单的源代码复制到 simple JSP 中 使用中提到的单独部署 http wiki orbeon com forms
  • 用于在命令提示符下运行 .exe 的 Bat 文件

    我想创建一个 bat 文件 这样我只需单击它即可运行 svcutil exe language cs out generatedProxy cs config app config http localhost 8000 ServiceMo
  • 如何使用不同的包(不仅仅是不同的包版本号)覆盖嵌套的 npm 子依赖项?

    Overview 我在解决由以下人员识别的 ReDoS 漏洞时遇到问题npm audit 我的应用程序有一个嵌套的子依赖项ansi html很容易受到攻击 但不幸的是 似乎维护人员擅离职守 https github com Tjatse a
  • iOS 上“由于未捕获的异常而终止应用程序”

    我有一个for在我的代码中循环 当继续执行此 for 循环时 我的应用程序崩溃并在控制台上打印以下消息 Terminating app due to uncaught exception NSRangeException reason NS
  • 如何指定显示?

    当我通过 SSH 运行一些程序时 例如firefox 我收到一个错误 Error no display specified 我想打开许多显示器 仍然显示stdout每个程序的 最初的问题 如何指定显示以获得多显示节目 Pablo Santa
  • 查找 MSBuildProjectDirectory 父目录

    MSBuild 3 5 我有以下项目结构 trunk MainSolution sln trunk Build MyBuild Proj trunk Library trunk etc 到目前为止 我一直在使用以下属性来查找项目根文件夹
  • Scala Case 类的更新操作

    我有两个相同类型的实例化案例类 case class Foo x Option String y Option String z Option String 让我们调用实例化的类 A 和 B val a Foo x Some foo y S