我想知道如何在列表中添加'partitionCount'方法,例如: (未经过测试,无耻地基于List.scala):
我是否必须创建自己的子类和隐式类型转换器?
(我最初的尝试有很多问题,所以这里有一个基于@Easy的答案):
class MyRichList[A](targetList: List[A]) {
def partitionCount(p: A => Boolean): (Int, Int) = {
var btrue = 0
var bfalse = 0
var these = targetList
while (!these.isEmpty) {
if (p(these.head)) { btrue += 1 } else { bfalse += 1 }
these = these.tail
}
(btrue, bfalse)
}
}
这是一个更适合Seq [...]的通用版本:
implicit def seqToRichSeq[T](s: Seq[T]) = new MyRichSeq(s)
class MyRichList[A](targetList: List[A]) {
def partitionCount(p: A => Boolean): (Int, Int) = {
var btrue = 0
var bfalse = 0
var these = targetList
while (!these.isEmpty) {
if (p(these.head)) { btrue += 1 } else { bfalse += 1 }
these = these.tail
}
(btrue, bfalse)
}
}
答案 0 :(得分:9)
你可以使用这样的隐式转换:
implicit def listToMyRichList[T](l: List[T]) = new MyRichList(l)
class MyRichList[T](targetList: List[T]) {
def partitionCount(p: T => Boolean): (Int, Int) = ...
}
而不是this
您需要使用targetList
。您无需延长List
。在这个例子中,我创建了一个隐式使用的简单包装器MyRichList
。
您可以通过为Traversable
定义包装器来进一步概括包装器,以便它可以用于其他集合类型,而不仅仅适用于List
:
implicit def listToMyRichTraversable[T](l: Traversable[T]) = new MyRichTraversable(l)
class MyRichTraversable[T](target: Traversable[T]) {
def partitionCount(p: T => Boolean): (Int, Int) = ...
}
另请注意,只有在范围内时才会使用隐式转换。这意味着,您需要import
它(除非您在定义它的同一范围内使用它)。
答案 1 :(得分:3)
正如 Easy Angel 已经指出的那样,使用隐式转换:
implicit def listTorichList[A](input: List[A]) = new RichList(input)
class RichList[A](val source: List[A]) {
def partitionCount(p: A => Boolean): (Int, Int) = {
val partitions = source partition(p)
(partitions._1.size, partitions._2.size)
}
}
另请注意,您可以根据partitionCount
轻松定义partinion
。然后你可以简单地使用:
val list = List(1, 2, 3, 5, 7, 11)
val (odd, even) = list partitionCount {_ % 2 != 0}
如果您对它是如何工作感到好奇,只需删除implicit
关键字并显式调用list2richList
转换(这是编译器在使用implicit
时透明地执行的操作)。< / p>
val (odd, even) = list2richList(list) partitionCount {_ % 2 != 0}
答案 2 :(得分:1)
Easy Angel是对的,但这种方法似乎没用。您已经count
获取“肯定”的数量,当然“否定”的数量为size
减去count
。
然而,为了贡献积极的东西,这里是原始方法的更多功能版本:
def partitionCount[A](iter: Traversable[A], p: A => Boolean): (Int, Int) =
iter.foldLeft ((0,0)) { ((x,y), a) => if (p(a)) (x + 1,y) else (x, y + 1)}