展平相同类型的嵌套列表

Pri*_*osK 3 scala review pattern-matching

假设我想要展平相同类型的嵌套列表...例如

    ListA(Element(A), Element(B), ListA(Element(C), Element(D)), ListB(Element(E),Element(F)))
Run Code Online (Sandbox Code Playgroud)

ListA包含相同类型的嵌套列表(ListA(Element(C), Element(D)))所以我想用它包含的值替换它,所以上面示例的结果应如下所示:

ListA(Element(A), Element(B), Element(C), Element(D), ListB(Element(E),Element(F)))
Run Code Online (Sandbox Code Playgroud)

当前类层次结构:

abstract class SpecialList() extends Exp {
    val elements: List[Exp]
}

case class Element(name: String) extends Exp

case class ListA(elements: List[Exp]) extends SpecialList {
        override def toString(): String = "ListA("+elements.mkString(",")+")"
}

case class ListB(elements: List[Exp]) extends SpecialList {
        override def toString(): String = "ListB("+elements.mkString(",")+")"
}

object ListA{def apply(elements: Exp*):ListA = ListA(elements.toList)}
object ListB{def apply(elements: Exp*):ListB = ListB(elements.toList)}
Run Code Online (Sandbox Code Playgroud)

我已经制定了三个有效的解决方案,但我认为必须有更好的方法来实现这个目标:

第一解决方案

def flatten[T <: SpecialList](parentList: T): List[Exp] = {
        val buf = new ListBuffer[Exp]

        for (feature <- parentList.elements) feature match {
            case listA:ListA if parentList.isInstanceOf[ListA] => buf ++= listA.elements
            case listB:ListB if parentList.isInstanceOf[ListB] => buf ++= listB.elements
            case _ => buf += feature
        }
        buf.toList
    }
Run Code Online (Sandbox Code Playgroud)

二解决方案:

def flatten[T <: SpecialList](parentList: T): List[Exp] = {
    val buf = new ListBuffer[Exp]

    parentList match {
        case listA:ListA => for (elem <- listA.elements) elem match {
                                case listOfTypeA:ListA => buf ++= listOfTypeA.elements
                                case _ => buf += elem
                            }

        case listB:ListB => for (elem <- listB.elements) elem match {
                                case listOfTypeB:ListB => buf ++= listOfTypeB.elements
                                case _ => buf += elem
                            }
    }

    buf.toList
}
Run Code Online (Sandbox Code Playgroud)

第三种方案

def flatten[T <: SpecialList](parentList: T): List[Exp] = parentList.elements flatMap {
    case listA:ListA if parentList.isInstanceOf[ListA] => listA.elements
    case listB:ListB if parentList.isInstanceOf[ListB] => listB.elements
    case other => List(other)
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,是否有更好,更通用的方法来实现相同的功能,因为在所有上三个解决方案中都有重复的代码?

小智 13

一个真正的功能方式.不使用变量.

def flatten[A](list: List[A]): List[A] = list match {
   case Nil => Nil
   case (ls: List[A]) :: tail => flatten(ls) ::: flatten(tail)
   case h :: tail => h :: flatten(tail)
}
Run Code Online (Sandbox Code Playgroud)

  • 我努力实现的东西,试图自己实现 - 我没有意识到你可以使用case(x:Type):: xs =>为第一个元素提供一个类型,我从编译器收到一个错误(它预期a =>) (3认同)