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)
之类的可能有一些拼写错误,我在用手机。另请注意,如果底层 Seqs 是 List 但如果您有 Vectors 它将具有合理的性能,这可能会非常低效;您也可以使用 Iterator 或 View 来避免分配 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,如何使用函数式编程在复杂序列之间进行一种连接操作?的主要内容,如果未能解决你的问题,请参考以下文章