Scala,如何使用函数式编程在复杂序列之间进行一种连接操作?

Posted

技术标签:

【中文标题】Scala,如何使用函数式编程在复杂序列之间进行一种连接操作?【英文标题】:Scala, how to use functional programming to do a kind of join operation in between to complex sequences? 【发布时间】:2021-08-02 10:10:36 【问题描述】:

假设我有一个 Seq[Seq[String]] 序列,比如

val seq = for (i <- (1 to 50) toSeq) yield Seq(s"foo$i", s"bar$i")

,即

List(List("foo1", "bar1"), List("foo2", "bar2"), ..., List("foo50", "bar50"))

我也有一个索引元组,比如说 ((5, 10), (13, 17), (25, 33), (42, 49))

我想要得到的是过滤 seq,只得到那些索引在第二个元组范围之间的,我想在最后一个位置添加一个新的 id。 结果应该是:

List(List("foo5", "bar5", "0"), List("foo6", "bar6", "0")..., List("foo10", "bar10", "0"), List("foo13", "bar13", "1"), List("foo14", "bar14", "1")..., List("foo17", "bar17", "1"), List("foo25", "bar25", "2"), List("foo26", "bar26", "2")... List("foo33", "bar33", "2"), List("foo42", "bar42", "3"), List("foo43", "bar43", "3")..., List("foo48", "bar48", "3"), List("foo49", "bar49", "3"))

我可以使用过程式编程来实现这一点,但是代码味道很难看。如何以 scala 风格的函数式方式做到这一点?

【问题讨论】:

expandRanges、zipWith、过滤器 indexes.zipWithIndex.map case ((start, end), idx) => seq.slice(start, end).map(_ + idx.toString) 之类的可能有一些拼写错误,我在用手机。另请注意,如果底层 SeqsList 但如果您有 Vectors 它将具有合理的性能,这可能会非常低效;您也可以使用 IteratorView 来避免分配 zip WithIndex一口气。 @LuisMiguelMejíaSuárez flatMap 不是 map? @Bergi 我猜map OP 想要一个嵌套的 Seq 但正如我所说我还没有编译代码,我认为编译器不是最好的 (特别是现在我要睡觉了)所以也许我错过了一些东西。我的想法是,如果我的 sn-p 确实帮助了 OP,我明天会发布一个正确的答案。 【参考方案1】:

一般来说,连接类型的操作可以很容易地使用 for 推导式来表达:

val ranges = Seq((5, 10), (13, 17), (25, 33), (42, 49))
for 
  i <- (1 to 50).toSeq
  ((lower, upper), j) <- ranges.zipWithIndex
  if i >= lower && i <= upper
 yield List(s"foo$i", s"bar$i", j.toString)

但是请注意,这需要的时间与两个列表长度的乘积成正比。如果这些变得足够大,您将需要更优化的解决方案。

【讨论】:

请您详细说明时间比例如何与两个列表长度的乘积增加以及如何制定更优化的解决方案,谢谢

以上是关于Scala,如何使用函数式编程在复杂序列之间进行一种连接操作?的主要内容,如果未能解决你的问题,请参考以下文章

如何理解Scala的函数式编程

scala函数式编程

重学scala:scala函数式编程与高阶函数

预售┃Scala与Clojure函数式编程模式:Java虚拟机高效编程

Scala函数式编程 函数式的错误处理

scala函数式编程 scala基础语法介绍