Вот эскиз в Скала.Каким бы ни был ваш язык, сначала вы должны как-то представить древовидную структуру данных:
sealed trait NestedArray
case class Leaf(arr: Array[Int]) extends NestedArray {
override def toString = arr.mkString("[", ",", "]")
}
case class Node(children: Array[NestedArray]) extends NestedArray {
override def toString =
children
.flatMap(_.toString.split("\n"))
.map(" " + _)
.mkString("[\n", "\n", "\n]")
}
object NestedArray {
def apply(ints: Int*) = Leaf(ints.toArray)
def apply(cs: NestedArray*) = Node(cs.toArray)
}
Единственная важная часть - это различие между листовыми узлами, которые содержат массивы целых чисел, и внутренними узлами, которые содержатих дочерние узлы в массивах.Методы toString
и дополнительные конструкторы не так важны, это в основном только для небольшой демонстрации ниже.
Теперь вы, по сути, хотите построить кодер-декодер, где часть encode
просто сглаживает все, иdecode
part принимает в качестве аргумента другой вложенный массив и преобразовывает плоский массив в форму вложенного массива.Выравнивание очень простое:
def encode(a: NestedArray): Array[Int] = a match {
case Leaf(arr) => arr
case Node(cs) => cs flatMap encode
}
Восстановление структуры также не так сложно.Я решил отслеживать позицию в массиве, передавая явный int
-индекс:
def decode(
shape: NestedArray,
flatArr: Array[Int]
): NestedArray = {
def recHelper(
startIdx: Int,
subshape: NestedArray
): (Int, NestedArray) = subshape match {
case Leaf(a) => {
val n = a.size
val subArray = Array.ofDim[Int](n)
System.arraycopy(flatArr, startIdx, subArray, 0, n)
(startIdx + n, Leaf(subArray))
}
case Node(cs) => {
var idx = startIdx
val childNodes = for (c <- cs) yield {
val (i, a) = recHelper(idx, c)
idx = i
a
}
(idx, Node(childNodes))
}
}
recHelper(0, shape)._2
}
Ваш пример:
val original = NestedArray(
NestedArray(NestedArray(1, 2), NestedArray(3, 4), NestedArray(5, 6)),
NestedArray(NestedArray(7, 8, 9, 10))
)
println(original)
Вот что этовыглядит как ASCII-дерево:
[
[
[1,2]
[3,4]
[5,6]
]
[
[7,8,9,10]
]
]
Теперь воссоздайте дерево той же формы из другого массива:
val flatArr = Array(1, 2, 3, 4, 12515, 25125, 12512, 8, 9, 10)
val reconstructed = decode(original, flatArr)
println(reconstructed)
это дает вам:
[
[
[1,2]
[3,4]
[12515,25125]
]
[
[12512,8,9,10]
]
]
Я надеюсь, что это должно быть более или менее понятно для любого, кто занимается функциональным программированием на не слишком отдаленном потомке ML.