使用Scala实现链表(List)数据结构

这个例子来源于scala圣经级教程《Functional Programming in Scala》,由于本人跟着书中的代码敲了一遍,然后写了点测试代码验证了一下正确性,所以就放在这做个备忘吧。贴出来只是为了方便自己得意,如果看不懂,但是又感兴趣的就去看原书吧偷笑偷笑偷笑

package fpinscala.datastructures

sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]

object List {

  def sum(ints: List[Int]): Int = ints match {
    case Nil => 0
    case Cons(x, xs) => x + sum(xs)
  }

  def product(ds: List[Double]): Double = ds match {
    case Nil => 1.0
    case Cons(0.0, _) => 0.0
    case Cons(x, xs) => x * product(xs)
  }

  def apply[A](as: A*): List[A] = if (as.isEmpty) Nil else Cons(as.head, apply(as.tail: _*))


  def append[A](a1: List[A], a2: List[A]): List[A] =
    a1 match {
      case Nil => a2
      case Cons(h, t) => Cons(h, append(t, a2))
    }

  def sum2(ns: List[Int]) = foldRight(ns, 0)(_ + _)

  def product2(ns: List[Double]) = foldRight(ns, 1.0)(_ * _)

  def tail[A](l: List[A]): List[A] = l match {
    case Nil => sys.error("tail of empty list")
    case Cons(_, t) => t
  }

  def setHead[A](l: List[A], h: A): List[A] = l match {
    case Nil => sys.error("tail of empty list")
    case Cons(_, t) => Cons(h, t)
  }

  def drop[A](l: List[A], n: Int): List[A] =
    if (n <= 0) l else l match {
      case Nil => Nil
      case Cons(_, t) => drop(t, n - 1)
    }

  def dropWhile[A](l: List[A], f: A => Boolean): List[A] =
    l match {
      case Cons(h, t) if f(h) => dropWhile(t, f)
      case _ => l
    }

  def init[A](l: List[A]): List[A] = l match {
    case Nil => sys.error("init of empty list")
    case Cons(_, Nil) => Nil
    case Cons(h, t) => Cons(h, init(t))
  }

  def init2[A](l: List[A]): List[A] = {
    import scala.collection.mutable.ListBuffer;
    val buf = new ListBuffer[A];

    @annotation.tailrec
    def go(cur: List[A]): List[A] = cur match {
      case Nil => sys.error("init of empty list")
      case Cons(_, Nil) => List(buf.toList: _*)
      case Cons(h, t) => buf += h; go(t)
    }

    go(l)
  }

  def lenght[A](l: List[A]): Int = foldRight(l, 0)((_, acc) => acc + 1)

  def sum3(l: List[Int]): Int = foldLeft(l, 0)(_ + _)

  def product3(l: List[Double]) = foldLeft(l, 1.0)(_ * _)

  def length2[A](l: List[A]): Int = foldLeft(l, 0)((acc, _) => acc + 1)

  def reverse[A](l: List[A]): List[A] = foldLeft(l, List[A]())((acc, h) => Cons(h, acc))

  def foldRightViaFoldLeft[A, B](l: List[A], z: B)(f: (A, B) => B): B = foldLeft(reverse(l), z)((b, a) => f(a, b))

  def foldRight[A, B](as: List[A], z: B)(f: (A, B) => B): B =
    as match {
      case Nil => z
      case Cons(x, xs) => f(x, foldRight(xs, z)(f))
    }

  @annotation.tailrec
  def foldLeft[A, B](l: List[A], z: B)(f: (B, A) => B): B = l match {
    case Nil => z
    case Cons(h, t) => foldLeft(t, f(z, h))(f)
  }

  def foldRightViaFoldLeft_1[A, B](l: List[A], z: B)(f: (A, B) => B) =
    foldLeft(l, (b: B) => b)((g, a) => b => g(f(a, b)))(z)

  def foldLeftViaFoldRight[A, B](l: List[A], z: B)(f: (B, A) => B): B =
    foldRight(l, (b: B) => b)((a, g) => b => g(f(b, a)))(z)

  def appendViaFoldRight[A](l: List[A], r: List[A]): List[A] =
    foldRight(l, r)(Cons(_, _))

  def concat[A](l: List[List[A]]): List[A] = foldRight(l, Nil: List[A])(append)

  def add1(l: List[Int]): List[Int] = foldRight(l, Nil: List[Int])((h, t) => Cons(h + 1, t))

  def doubleToString(l: List[Double]): List[String] =
    foldRight(l, Nil: List[String])((h, t) => Cons(h.toString, t))


  def map[A, B](l: List[A])(f: A => B): List[B] =
    foldRight(l, Nil: List[B])((h, t) => Cons(f(h), t))


  def map_1[A, B](l: List[A])(f: A => B): List[B] =
    foldRightViaFoldLeft(l, Nil: List[B])((h, t) => Cons(f(h), t))

  def map_2[A, B](l: List[A])(f: A => B): List[B] = {
    val buf = new scala.collection.mutable.ListBuffer[B]

    def go(l: List[A]): Unit = l match {
      case Nil => ()
      case Cons(h, t) => buf += f(h); go(t)
    }

    go(l)
    List(buf.toList: _*)
  }

  def filter[A](l: List[A])(f: A => Boolean): List[A] =
    foldRight(l, Nil: List[A])((h, t) => if(f(h)) Cons(h, t) else t)

  def filter_1[A](l: List[A])(f: A => Boolean): List[A] =
    foldRightViaFoldLeft(l, Nil: List[A])((h, t) => if(f(h)) Cons(h, t) else t)


  def filter_2[A](l: List[A])(f: A => Boolean): List[A] = {
    val buf = new scala.collection.mutable.ListBuffer[A]

    def go(l: List[A]): Unit = l match {
      case Nil => ()
      case Cons(h, t) => if(f(h)) buf += h; go(t)
    }
    go(l)
    List(buf.toList: _*)
  }

  def flatMap[A, B](l: List[A])(f: A => List[B]): List[B] =
    concat(map(l)(f))

  def filterViaFlatMap[A](l: List[A])(f: A => Boolean): List[A] =
    flatMap(l)(a => if(f(a)) List(a) else Nil)

  def addPairWise(a: List[Int], b: List[Int]): List[Int] = (a, b) match {
    case (Nil, _) => Nil
    case (_, Nil) => Nil
    case (Cons(h1, t1), Cons(h2, t2)) => Cons(h1 + h2, addPairWise(t1, t2))
  }

  def zipWith[A, B, C](a: List[A], b: List[B])(f: (A, B) => C): List[C] = (a, b) match {
    case (Nil, _) => Nil
    case (_, Nil) => Nil
    case (Cons(h1, t1), Cons(h2, t2)) => Cons(f(h1, h2), zipWith(t1, t2)(f))
  }

  @annotation.tailrec
  def startWith[A](l: List[A], prefix: List[A]): Boolean = (l, prefix) match {
    case (_, Nil) => true
    case (Cons(h, t), Cons(h2, t2)) if h == h2 => startWith(t, t2)
    case _  => false
  }

  @annotation.tailrec
  def hasSubsequence[A](sup: List[A], sub: List[A]): Boolean = sup match {
    case Nil => sub == Nil
    case _ if startWith(sup, sub) => true
    case Cons(h, t) => hasSubsequence(t, sub)
  }



  /**
    * 测试
    * @author lihong10 2018/7/3 10:07:00
    * @param args
    * return void
    */
  def main(args: Array[String]): Unit = {


    val liStr: List[String]  = List("wo", "shi", "zhong", "guo", "ren", "ni", "shi", "sha", "bi")
    val liStrSub = List("ni", "shi", "sha", "bi")
    println(liStr)

    val hasSubSeq = List.hasSubsequence(liStr, liStrSub)
    println(hasSubSeq)

    val doubleELe = List.map(liStr)((a: String)  => a * 2)
    println(doubleELe)

    val lenGt3 = List.filter(liStr)((a: String) => a.length > 3)
    println(lenGt3)


    println(List.lenght(liStr))

    val liInt = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
    val add1 = List.add1(liInt)
    println(add1)

    println("sum:" + List.sum(liInt))


    println("foldLeft with 1000: " + List.foldLeft(liInt, 1000)(_ + _))

    println(List.reverse(liInt))

    val init = List.init(liInt)
    println("init: " + init)

    val tail = List.tail(liInt)
    println("tail: " + tail)

    val dropLe5 = List.dropWhile(liInt, (a: Int) => a <= 5)
    println(dropLe5)

    val lili = List(List(1, 3, 5, 7), List(2, 4, 6, 8))
    val concated = List.concat(lili)
    println(concated)

    val zipList = List.zipWith(List(1, 3, 5, 7), List(2, 4, 6, 8))((_, _))
    println(zipList)

    val addPair = List.addPairWise(List(1, 2, 3, 4), List(4, 3, 2, 1))
    println(addPair)


    val join = List.foldRightViaFoldLeft(List(1, 3, 5, 7, 9, 11, 13, 15, 17, 19), "")((a: Int, b: String) => b + a.toString)
    println(join)
  }

}








上述代码的运行结果是:

Cons(wo,Cons(shi,Cons(zhong,Cons(guo,Cons(ren,Cons(ni,Cons(shi,Cons(sha,Cons(bi,Nil)))))))))
true
Cons(wowo,Cons(shishi,Cons(zhongzhong,Cons(guoguo,Cons(renren,Cons(nini,Cons(shishi,Cons(shasha,Cons(bibi,Nil)))))))))
Cons(zhong,Nil)
9
Cons(2,Cons(3,Cons(4,Cons(5,Cons(6,Cons(7,Cons(8,Cons(9,Cons(10,Nil)))))))))
sum:45
foldLeft with 1000: 1045
Cons(9,Cons(8,Cons(7,Cons(6,Cons(5,Cons(4,Cons(3,Cons(2,Cons(1,Nil)))))))))
init: Cons(1,Cons(2,Cons(3,Cons(4,Cons(5,Cons(6,Cons(7,Cons(8,Nil))))))))
tail: Cons(2,Cons(3,Cons(4,Cons(5,Cons(6,Cons(7,Cons(8,Cons(9,Nil))))))))
Cons(6,Cons(7,Cons(8,Cons(9,Nil))))
Cons(1,Cons(3,Cons(5,Cons(7,Cons(2,Cons(4,Cons(6,Cons(8,Nil))))))))
Cons((1,2),Cons((3,4),Cons((5,6),Cons((7,8),Nil))))
Cons(5,Cons(5,Cons(5,Cons(5,Nil))))
191715131197531


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是使用 Scala 实现目录及文件 copy 操作的示例代码: ```scala import java.io._ object FileCopy { def main(args: Array[String]): Unit = { val source = new File("path/to/source/directory") val destination = new File("path/to/destination/directory") copyDirectory(source, destination) } def copyDirectory(source: File, destination: File): Unit = { if (source.isDirectory) { if (!destination.exists()) { destination.mkdir() } val files = source.listFiles() for (f <- files) { val newFile = new File(destination.getAbsolutePath + File.separator + f.getName) copyDirectory(f, newFile) } } else { val in = new FileInputStream(source) val out = new FileOutputStream(destination) val buffer = new Array[Byte](1024) var length = in.read(buffer) while (length > 0) { out.write(buffer, 0, length) length = in.read(buffer) } in.close() out.close() } } } ``` 在上述代码中,我们首先定义了源目录和目标目录,然后调用 `copyDirectory` 方法来执行目录和文件的复制操作。如果源目录是一个目录,我们会检查目标目录是否存在,如果不存在则创建它,并且遍历源目录中的所有文件和子目录。对于每个文件,我们都会创建一个新的文件对象,并递归调用 `copyDirectory` 方法来复制文件到目标目录中。如果源目录是一个文件,我们会使用 `FileInputStream` 和 `FileOutputStream` 来读取和写入文件内容,并使用一个缓冲区来提高性能。最后,我们关闭输入和输出流并退出方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值