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

scala – 这个递归列表如何平坦化?

发布时间:2020-12-16 18:57:27 所属栏目:安全 来源:网络整理
导读:在 Scala邮件列表之后的一个 this was asked and answered 凯文: Given some nested structure: List[List[...List[T]]] what’s the best (preferably type-safe) way to flatten it to a List[T] 加斯帕: A combination of implicits and default argume
在 Scala邮件列表之后的一个 this was asked and answered

凯文:

Given some nested structure: List[List[...List[T]]]
what’s the best (preferably type-safe) way to flatten it to a List[T]

加斯帕:

A combination of implicits and default arguments works:

case class Flat[T,U](fn : T => List[U]) 

implicit def recFlattenFn[T,U](implicit f : Flat[T,U] = Flat((l : T) 
=> List(l))) = 
   Flat((l : List[T]) => l.flatMap(f.fn)) 

def recFlatten[T,U](l : List[T])(implicit f : Flat[List[T],U]) = f.fn(l)

例子:

scala> recFlatten(List(1,2,3)) 
res0: List[Int] = List(1,3) 

scala> recFlatten(List(List(1,3),List(4,5))) 
res1: List[Int] = List(1,3,4,5) 

scala> recFlatten(List(List(List(1,5)),List(List(6,7)))) 
res2: List[Int] = List(1,5,6,7)

我一直在看这个代码一段时间.我不知道它是如何工作的.似乎有一些递归涉及…有人可以散发光吗?这个模式有其他的例子,它有一个名字吗?

解决方法

哦,哇,这是一个老的!我将首先清理代码,并将其与现行惯用惯例相一致:

case class Flat[T,U](fn: T => List[U]) 

implicit def recFlattenFn[T,U](
  implicit f: Flat[T,U] = Flat((xs: T) => List(xs))
) = Flat((xs: List[T]) => xs flatMap f.fn)

def recFlatten[T,U](xs: List[T3])(implicit f: Flat[List[T],U]) = f fn xs

然后,不用多说,分解代码.首先,我们有Flat类:

case class Flat[T,U](fn: T => List[U])

这只不过是函数T =>的命名包装器列表[U],当给定一个类型为T的实例时,将构建一个List [U]的函数.请注意,这里的T也可以是List [U]或U,或List [List [List [U] ]]等.通常,这样的函数可以直接指定为参数的类型.但是我们将使用这个隐含的,所以命名的包装器避免任何隐含冲突的风险.

然后,从recFlatten向后工作:

def recFlatten[T,U](xs: List[T])(implicit f: Flat[List[T],U]) = f fn xs

该方法将采用xs(List [T])并将其转换为U.为了实现这一点,它定位了一个隐含的Flat [T,U]实例,并调用附带的函数fn

然后,真正的魔法:

implicit def recFlattenFn[T,U] = Flat((xs: T) => List(xs))
) = Flat((xs: List[T]) => xs flatMap f.fn)

这满足recFlatten所需的隐式参数,它也需要另一个隐式参数.最关键的是

> recFlattenFn可以作为自己的隐式参数
>它返回一个Flat [List [X],X],所以recFlattenFn只会被隐式解析为Flat [T,U],如果T是一个列表
>如果隐式解析失败(即T不是列表),隐式f可以回退到默认值

也许这在一个例子的上下文中是最好的理解的:

recFlatten(List(List(1,5)))

>类型T推断为List [List [Int]]
对于’Flat [List [List [Int]],尝试进行隐式查找
>这被一个递归定义的recFlattenFn匹配

一般来说:

recFlattenFn[List[List[Int]],U] ( f =
  recFlattenFn[List[Int],U] ( f =
    Flat[Int,U]((xs: T) => List(xs)) //default value
  )
)

请注意,recFlattenFn将仅匹配Flat [List [X],X]和类型参数[Int,_]在此匹配中失败的隐含搜索,因为Int不是列表.这是什么触发回退到默认值.

类型推断也可以向上运行该结构,在每个递归级别解析U参数:

recFlattenFn[List[List[Int]],Int] ( f =
  recFlattenFn[List[Int],Int] ( f =
    Flat[Int,Int]((xs: T) => List(xs)) //default value
  )
)

这只是一个平面实例的嵌套,每个(最内层除外)执行一个flatMap操作来展开嵌套列表结构的一个层次.最内层的Flat简单地将所有的单个元素包装在单个列表中.

证明完毕

(编辑:李大同)

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

    推荐文章
      热点阅读