我有一些看起来像一个容易解决的问题,我想用Scala在功能上解决,但无法弄明白。 我正在学习Scala,并希望确保使用函数式编程原理完成它。下面的代码片段(甚至不起作用......)是我管理的所有内容 它仍然有一个可变的变量...... 任何帮助表示赞赏。
基本上我有一个集合列表,我想加入所有具有共同元素的集合。 并递归地应用它,即继续加入列表中的集合,直到它们只剩下脱节。
所以输入
List(Set(1,2,3), Set(4,1,5), Set(6,2,7), Set(8,9))
我想获得List(Set(1,2,3,4,5,6,7), Set(8,9))
。
我的代码如下 - 再次它没有完全发挥作用。
def mergeSets(sets: List[Set[Int]]): List[Set[Int]] = {
@tailrec
def go(list: List[Set[Int]], result: List[Set[Int]]): List[Set[Int]] = list match {
case Nil => result
case h :: t => {
var tmpResult = result
tmpResult = list.filter(_.intersect(h).nonEmpty).map(_ ++ h) ::: result
tmpResult = list.filter(_.intersect(h).isEmpty) ::: tmpResult
go(t, tmpResult.toSet.toList)
}
}
go(sets, List())
}
答案 0 :(得分:1)
我会使用元组返回类型而不是List,因为您希望该位置具有含义。我在下面使用的策略是折叠每个集合,对于每个集合,如果有另一个集合具有任何公共元素,则添加到第一个元组位置,否则添加到第二个元组。
def mergeSets(sets: Set[Int]*): (Set[Int], Set[Int]) = {
sets.foldLeft((Set.empty[Int], Set.empty[Int])) { case ((c, d), n) =>
if (sets.exists(s => n.exists(s.contains) && s != n))
(c ++ n, d)
else
(c, d ++ n)
}
}
val (common, disjointed) = mergeSets(Set(1,2,3), Set(4,1,5), Set(6,2,7), Set(8,9))
println(common)
// Set(5, 1, 6, 2, 7, 3, 4)
println(disjointed)
// Set(8, 9)
答案 1 :(得分:1)
这是“一线”解决方案,它结合了更高阶的函数来获得所需的结果:
val l = val l = List(Set(1,2,3), Set(4,1,5), Set(6,2,7), Set(8,9))
(for (el <- l) yield
l.foldLeft(el)((s, x) =>
if (s.intersect(x).size > 0) s.union(x) else s)
).toSet
主要思想是迭代每一组,并产生所有适当集合的联合。这里唯一的技巧是使用toSet
来删除重复项。