scala: добавить метод в список? - PullRequest
5 голосов
/ 08 августа 2011

Мне было интересно, как добавить метод '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)
  }
}

Ответы [ 3 ]

9 голосов
/ 08 августа 2011

Вы можете использовать неявное преобразование следующим образом:

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 s:

implicit def listToMyRichTraversable[T](l: Traversable[T]) = new MyRichTraversable(l)

class MyRichTraversable[T](target: Traversable[T]) {
    def partitionCount(p: T => Boolean): (Int, Int) = ...
}

Также обратите внимание, что неявное преобразование будет использоваться, только если оно находится в области видимости.Это означает, что вам нужно import (если вы не используете его в той же области, где вы его определили).

3 голосов
/ 08 августа 2011

Как уже указывалось 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).

val (odd, even) = list2richList(list) partitionCount {_ % 2 != 0}
1 голос
/ 08 августа 2011

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)}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...