Ключевая проблема здесь - «как мне объединить элементы в items
в большой список?». Мы можем упростить задачу до меньшего: «Как мне объединить 2 Any
s, которые могут быть T
или Node<T>
, в один список, представленный Node<T>
?». (Это то, что делает combine2Anys
ниже). Вы можете легко увидеть, что существует 4 случая этой проблемы:
- первый элемент -
Node<T>
, второй элемент - T
, - оба элемента
Node<T>
- первый раз
T
, второй элемент Node<T>
- оба элемента
T
Вам просто нужно обрабатывать каждый случай по очереди. Затем используйте этот метод с первыми двумя элементами из items
, затем с результатом этого и третьего элемента, затем с результатом этого и четвертого элемента и т. Д.
class Node<T> {
var data: T
var next: Node<T>?
init(_ items: Any...) {
func combine2Anys(_ x: Any, _ y: Any) -> Node<T> {
switch (x, y) {
case (let node as Node<T>, let t as T):
node.end.next = Node(data: t, next: nil)
return node
case (let node1 as Node<T>, let node2 as Node<T>):
node1.end.next = node2
return node1
case (let t as T, let node as Node<T>):
return Node(data: t, next: node)
case (let t1 as T, let t2 as T):
return Node(data: t1, next: Node(data: t2, next: nil))
default:
// something other than Node<T> and T are in the passed in array
fatalError()
}
}
if items.count == 0 {
fatalError() // it's undefined what we should do when items is empty
} else if items.count == 1 {
data = items.first as! T
next = nil
} else {
var combined = combine2Anys(items[0], items[1])
for i in 2..<items.count {
combined = combine2Anys(combined, items[i])
}
data = combined.data
next = combined.next
}
}
// find the last node of the list
var end: Node<T> {
var node = self
while node.next != nil {
node = node.next!
}
return node
}
init(data: T, next: Node<T>?) {
self.data = data
self.next = next
}
}
Использование:
let list = Node<Int>(1, Node<Int>(2, 15), 4, Node<Int>(5, Node<Int>(7, 9)))
Обратите внимание, что вы должны постоянно использовать один и тот же общий c тип.
Но на самом деле это действительно некрасиво, в основном из-за слепков и прочего. Вы теряете всю безопасность типов во время компиляции. Я предполагаю, что это одно из тех «странных требований домашней работы». Если бы я сделал это в реальном мире, я бы изменил использование на:
let list = Node(Node(1), Node(Node(2), Node(15)), Node(4), Node(Node(5), Node(Node(7), Node(9))))
И вместо этого у меня были бы эти два инициализации:
init(_ items: Node<T>...) {
if items.count == 1 {
data = items.first as! T
next = nil
} else {
items[0].end.next = items[1]
for i in 2..<items.count {
items[i - 1].end.next = items[i]
}
data = items[0].data
next = items[0].next
}
}
init(_ item: T, next: Node<T>? = nil) {
self.data = item
self.next = next
}