首页 > 技术文章 > scala中的函数组合-谓词组合

taich-flute 2017-03-12 19:54 原文

继续上一篇关于函数组合的介绍:

谓词组合

还以歌曲过滤器为例说明,前面的歌曲过滤器只能传递一个过滤条件,如果筛选出满足多个条件的歌曲,可以用到“谓词组合”。

object SongDemo3 {
  type SongFilter = Song => Boolean

  /**
    * 给定一个谓词函数predicate,返回和predicate对立的结果.
    *
    * @param predicate
    * @tparam T
    * @return
    */
  def reverse[T](predicate: T => Boolean) = (a: T) => !predicate(a)

  def findSingerSongs: Set[String] => SongFilter =
    singerNames =>
      song => song.singers.exists(singerNames)

  def removeSingerSongs = findSingerSongs.andThen(reverse(_))

  type HotChecker = Int => Boolean

  def hotFilter: HotChecker => SongFilter =
    f =>
      song => f(song.hot)

  def findTopHotSongs: Int => SongFilter =
    hot =>
      hotFilter(_ >= hot)

  def findLowHotSongs: Int => SongFilter =
    hot =>
      hotFilter(_ < hot)


  /**
    * 检查是否会有一个谓词输入a为真.
    *
    * @param predicates
    * @tparam T
    * @return
    */
  def any[T](predicates: (T => Boolean)*): T => Boolean =
    a => predicates.exists(pred => pred(a))

  /**
    * 是否所有的谓词输入都不为真.
    *
    * @param predicates
    * @tparam T
    * @return
    */
  def none[T](predicates: (T => Boolean)*) = reverse(any(predicates: _*))

  /**
    * 检查是否每个谓词输入都为真.
    *
    * @param predicates
    * @tparam T
    * @return
    */
  def every[T](predicates: (T => Boolean)*) = none(predicates.view.map(reverse(_)): _*)


  def fingSongs(songs: Seq[Song], f: SongFilter) = songs.filter(f)

  def main(args: Array[String]) {

    //过滤器,过滤掉歌手名为刘德华的歌曲.
    val exculdeSingerFilter = removeSingerSongs(Set("刘德华"))

    val combineFilter: SongFilter = every(
      removeSingerSongs(Set("刘德华")),
      findTopHotSongs(100),
      findLowHotSongs(10000)

    )


    val songs = List(
      Song(1, "今天", List("刘德华"), 101),
      Song(2, "笨小孩", List("刘德华"), 20),
      Song(3, "七里香", List("周杰伦"), 501),
      Song(4, "吻别", List("张学友"), 20000),
      Song(5, "浮夸", List("陈奕迅"), 99)
    )


    fingSongs(songs, combineFilter).foreach(println)

  }
}

输出结果:

Song(3,七里香,List(周杰伦),501)

推荐阅读