Spłaszczanie zagnieżdżonych list tego samego typu
Powiedzmy, że chcę spłaszczyć zagnieżdżone listy tego samego typu ... Na przykład
<code> ListA(Element(A), Element(B), ListA(Element(C), Element(D)), ListB(Element(E),Element(F))) </code>
ListA
zawiera zagnieżdżoną listę tego samego typu (ListA(Element(C), Element(D))
) więc chcę go zastąpić wartościami, które zawiera, więc wynik górnego przykładu powinien wyglądać tak:
<code>ListA(Element(A), Element(B), Element(C), Element(D), ListB(Element(E),Element(F))) </code>
Bieżąca hierarchia klas:
<code>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)} </code>
Zrobiłem trzy rozwiązania, które działają, ale myślę, że musi być lepszy sposób na osiągnięcie tego:
Pierwsze rozwiązanie:
<code>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 } </code>
Drugie rozwiązanie:
<code>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 } </code>
Trzecie rozwiązanie
<code>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) } </code>
Moje pytanie brzmi: czy istnieje jakikolwiek lepszy, bardziej ogólny sposób na osiągnięcie takiej samej funkcjonalności, jak we wszystkich trzech wyższych rozwiązaniach jest powtórzenie kodu?