加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala中嵌套列表的深度反转

发布时间:2020-12-16 09:19:49 所属栏目:安全 来源:网络整理
导读:我想在Scala中递归地反转列表列表. 我在Python中写了深层次的逆转,如下所示: def deepReverse(items): if type(items) == list: return [deepReverse(item) for item in reversed(items)] else: return items 我如何在Scala中做同样的事情?问题不在于算法
我想在Scala中递归地反转列表列表.

我在Python中写了深层次的逆转,如下所示:

def deepReverse(items):
    if type(items) == list:
        return [deepReverse(item) for item in reversed(items)]
    else: 
        return items

我如何在Scala中做同样的事情?问题不在于算法 – 它是类型的东西,我是较新的.

我需要使用[T]或List [List [T]]的列表,或T的列表和Ts的列表的任何深度的功能.根据我在其他地方看到的一个例子,我试着做一个案例课.我不想要一个只返回Any并接受Any的函数;感觉就像作弊.

case class NL[+T](val v : Either[List[NL[T]],T])

尽管如此,我也不太清楚我的类型是否平衡.我是Scala的新手,但是我认为这将是一个完美的机会,可以把递归和打字弄乱.

解决方法

编写sschaef建议的类型类方法的版本实际上并不难,这将适用于任意嵌套列表:

trait Reverser[C] {
  def reverse(xs: C): C
}

implicit def rev[A](implicit ev: Reverser[A] = null) = new Reverser[List[A]] {
  def reverse(xs: List[A]) =
    Option(ev).map(r => xs map r.reverse).getOrElse(xs).reverse
}

def deepReverse[A](xs: A)(implicit ev: Reverser[A]): A = ev.reverse(xs)

我们的rev方法中的隐含参数ev证明A本身是可逆的,如果ev是null,这意味着它不是.如果我们有这样的证据表明A是可逆的,我们用它来扭转我们的List [A]的元素(这是地图正在做的),然后我们反转列表本身.如果我们没有这个证据(getOrElse的情况),我们可以反转列表.

我们可以像这样简洁地(但可能更有效地)写入rev:

implicit def rev[A](implicit ev: Reverser[A] = null) = if (ev == null) {
  new Reverser[List[A]] {
    def reverse(xs: List[A]) = xs.reverse
  }
} else {
  new Reverser[List[A]] {
   def reverse(xs: List[A]) = (xs map ev.reverse).reverse
  }
}

要测试这两个版本之一,我们可以写下列内容:

scala> deepReverse(List.tabulate(3)(identity))
res0: List[Int] = List(2,1,0)

scala> deepReverse(List.tabulate(2,3) { case (a,b) => a + b })
res1: List[List[Int]] = List(List(3,2,1),List(2,0))

scala> deepReverse(List.tabulate(2,3,4,5,6) {
     |   case (a,b,c,d,e) => a + b + c + d + e
     | }).head.head.head.head
res2: List[Int] = List(15,14,13,12,11,10)

如预期

我应该补充说,以下是一个更常见的成语,就是在这样的情况下得到这个意思:

trait ReverserLow {
  implicit def listReverser[A] = new Reverser[List[A]] {
    def reverse(xs: List[A]) = xs.reverse
  }
}

object ReverserHigh extends ReverserLow {
  implicit def nestedListReverser[A](implicit ev: Reverser[A]) =
    new Reverser[List[A]] {
      def reverse(xs: List[A]) = xs.map(ev.reverse).reverse
    }
}

import ReverserHigh._

如果我们刚刚在同一级别写了listReverser和nestedListReverser,当我们尝试反转列表列表时,我们会收到以下错误:

scala> deepReverse(List.tabulate(2,3)(_ + _))
<console>:12: error: ambiguous implicit values:
 both method listReverser...
 and method nestedListReverser...
 match expected type Reverser[List[List[Int]]]
              deepReverse(List.tabulate(2,3)(_ + _))

优先考虑两者的标准方法是将较低优先级隐含在一个特征(WhateverLow)中,另一个在扩展该特征的对象(WhateverHigh)中.在这样一个相当简单的情况下,尽管如此,在上面的rev方法中使用默认参数技巧更为简洁(更清晰).但是,您更有可能在其他人的代码中看到其他版本.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读