如何以纯函数式编程方式比较Scala中的ArrayBuffer[Array[String]]
解决ArrayBuffer[Array[String]]的纯函数式比较问题
嘿,我来帮你搞定这个嵌套集合的纯函数式比较问题!首先得先聊聊你现有的sameAs函数——它是用来判断两个Traversable集合是否包含完全相同的元素(不考虑顺序,且每个元素的出现次数一致),对吧?现在要把这个逻辑扩展到元素是Array[String]的嵌套集合,核心问题是:Scala里Array是引用类型,直接用==比较的是引用地址,不是内容,所以我们得先搞定嵌套数组的内容相等判断。
方案1:通用版(支持自定义元素相等判断)
我们可以先写个辅助函数,专门判断两个Array[String]的内容是否一致:
def arraysEqual(a: Array[String], b: Array[String]): Boolean = a.sameElements(b)
然后修改你的sameAs函数,让它接受一个自定义的相等判断函数,这样不管元素是什么类型,都能灵活适配:
def sameAs[A](c: Traversable[A], d: Traversable[A], eq: (A, A) => Boolean): Boolean = if (c.isEmpty) d.isEmpty else { // 把d拆分成"不等于当前c头部的元素"和"从第一个等于c头部的元素开始的剩余部分" val (e, f) = d span (x => !eq(c.head, x)) // 如果找不到匹配的元素,直接返回false if (f.isEmpty) false // 递归比较c的剩余部分,以及d中移除了匹配元素后的剩余部分 else sameAs(c.tail, e ++ f.tail, eq) }
现在用这个函数来比较你的嵌套集合:
import scala.collection.mutable.ArrayBuffer val buf1 = ArrayBuffer(Array("str1"), Array("str2"), Array("str3")) val buf2 = ArrayBuffer(Array("str1"), Array("str2"), Array("str3")) val areSame = sameAs(buf1, buf2, arraysEqual) // 结果为true
方案2:针对ArrayBuffer[Array[String]]的专用版
如果不需要通用能力,也可以直接修改原函数,把元素相等判断换成数组内容比较:
import scala.collection.mutable.ArrayBuffer def sameAsArrayBuffer(c: Traversable[Array[String]], d: Traversable[Array[String]]): Boolean = if (c.isEmpty) d.isEmpty else { val (e, f) = d span (x => !x.sameElements(c.head)) if (f.isEmpty) false else sameAsArrayBuffer(c.tail, e ++ f.tail) } // 调用示例 val buf1 = ArrayBuffer(Array("str1"), Array("str2"), Array("str3")) val buf2 = ArrayBuffer(Array("str2"), Array("str1"), Array("str3")) sameAsArrayBuffer(buf1, buf2) // 结果为true,因为不考虑顺序
补充说明
- 如果你需要的是考虑顺序的比较(也就是两个集合的元素顺序和内容完全一致),那不用这么复杂,直接用
sameElements方法就行:buf1.sameElements(buf2)。但看你原有的sameAs函数是不考虑顺序的,所以上面的方案保持了同样的逻辑。 - 这里用
span拆分集合是纯函数式的操作,没有副作用,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

