遍历混合类型的对象数组

3

我正在尝试一些非常简单的东西(至少在ObjC中是这样)。

我想遍历一个集合 - 比如一个由字符串和子数组组成的数组,并打印所有字符串,然后递归调用函数来遍历任何子数组。

我尝试了这样的代码:

func traverseCollection<T : Sequence>(collection: T)
{
    var generator = collection.generate()
    while let item = generator.next()
    {
        if let collectionItem = item as? Collection
        {
            traverseCollection(collectionItem)
        }
        else
        {
            println("item:", item)
        }
    }
}

但是我尝试将item向下转换时出现了错误:

无法从“T.GeneratorType.Element”向非@objc协议类型“Collection”进行向下转换 如果item可以作为Collection,则使用let collectionItem = item as? Collection

一个不那么通用的变体也会导致编译错误:

func traverseArray(array: Array<Any>)
{
       for item : Any in array
       {
            if let collectionItem = item as? Array<Any>
            {
                traverseArray(collectionItem)
            }
            else
            {
                println("item:", item)
            }
       }
}

以下两种情况可能会出现:要么导致 Playground 崩溃,要么无法编译:

Instruction does not dominate all uses!
  %10 = bitcast %swift.opaque* %9 to %Sq.20*, !dbg !235
  %3 = ptrtoint %Sq.20* %10 to i32, !dbg !232
Instruction does not dominate all uses!
  %T = load %swift.type** %3, align 4
  %4 = bitcast %swift.type* %T to i8*, !dbg !232
LLVM ERROR: Broken function found, compilation aborted!

我认为我正在错误地尝试解决它,但是我无法弄清楚如何在Swift中实现它。如果有人能指点我正确的方向,那就太好了。

2个回答

1
我会选择动态解决方案而不是递归解决方案,因为我不想冒险使用非确定性递归调用导致堆栈溢出的风险。
func printArray(array: Array<AnyObject>) -> () {
    var dynamicCollection: Array<AnyObject> = array
    dynamicCollection.unshare()
    do {
        let firstObject: AnyObject = dynamicCollection[0]
        if let myString: String = firstObject as? String {
            println(myString)
        } else if let myArray: Array<AnyObject> = firstObject as? Array {
            dynamicCollection += myArray
        }
        dynamicCollection.removeAtIndex(0)
    } while dynamicCollection.count > 0
}

那是我的测试数组,它仅包含String和另一个Array对象:
let myArray : Array<AnyObject> = ["string1", ["subString1", "subString2"], ["moreSubString1"], "string2", [["deepSubString1", "deepSubString2"], "justSubString1"]]

并且在我的控制台上结果看起来像这样:

string1
string2
subString1
subString2
moreSubString1
justSubString1
deepSubString1
deepSubString2

我喜欢这个解决方案,它确实解决了我的问题。但我仍然不知道为什么我的递归方法失败了。谢谢。 - Alexander Ney

0

首先,你提供的第二个示例明显是编译器的错误,请在bugreport.apple.com上报告。

这不是一个“纯”Swift解决方案,但它可以工作:

import Foundation
var array : NSArray = [1, 2, [3, 4]]

func printElements(array: NSArray) {
    for item : AnyObject in array {
        if let itemArray = item as? NSArray {
            printElements(itemArray)
        } else {
            println("\(item)")
        }
    }
}

printElements(array)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接