我试图编写一个简单的手动滚动函数来展平嵌套数组。我的代码可以作为switch语句正常工作,但是当我在一个"中为i而在0..arr.count"中递归调用它时。环。我查看传入的数组中的每个元素并说"如果这是一个数组,则调用该函数并将其传入,否则追加到输出数组"。
func flatten (input: [Any]) -> [Any] {
var outputArray = [Any] ()
for i in 0..<input.count {
let data = input[i];
(data is Array) ? outputArray += flatten(input: [data]) : outputArray.append(data)
}
return outputArray
}
因为我的函数参数必须是[Any]类型,所以我强制传递&#34;数据&#34;作为[数据]变回它。这只是强制函数不断解压缩数组,它只是卡在循环中。关于如何避免这种情况的任何建议?
答案 0 :(得分:0)
首先,您在相当复杂的情况下使用三元运算符(?:
)。如果您首先修改代码以使用if
语句,那么出现在outputArray.append(data)
- Generic parameter 'Element' could not be inferred
调用中的编译器错误会出现在一个更明智的地方(即if语句的行。)
该错误相对容易解决 - 只需将Array
替换为Array<Any>
,即可向我们提供:
func flatten(input: [Any]) -> [Any] {
var outputArray = [Any]()
for i in 0..<input.count {
let data = input[i]
if data is Array<Any> {
outputArray += flatten(input: [data])
} else {
outputArray.append(data)
}
}
return outputArray
}
此时,原始问题仍然存在,因为传递给flatten(input:)
的值为[data]
。我们知道,由于if
条件为true
,data
实际上属于Array<Any>
类型,因此值[data]
必须是Array<Array<Any>>
。相反,我们想要传入data
,这已经是一个数组。
你说你写[data]
的原因是因为参数必须是一个数组,所以你被编译器“强迫”了。实际上,编译器强制要求你做的唯一事情是传入一个声明为Array<Any>
类型的参数。我们确保data
是使用if
语句的数组,但data
仍然声明为Any
(因为它是input
的元素,它是Array<Any>
),因此编译器不知道它实际上是一个数组。
解决方案是 - 而不是使用if data is Array<Any>
来暂时确定data
是否是一个数组,而是立即抛出该信息 - 将data
转换为Array<Any>
。< / p>
新的if
语句变为if let dataArray = data as? Array<Any>
。语句data as? Array<Any>
尝试将data
转换为数组,如果成功则返回类型Array<Any>
,否则返回nil
。然后if let dataArray = ...
语句将值存储在dataArray
中,如果给定非true
值则返回nil
,如果给定false
,则返回nil
} value(这称为条件绑定)。
通过这样做,在true
语句的if
案例中,我们可以访问类型为dataArray
的值Array<Any>
- 与data
不同,仅声明为Any
。然后dataArray
可以传递到flatten(input:)
,并且不会嵌套在另一个Array
内。
func flatten(input: [Any]) -> [Any] {
var outputArray = [Any]()
for i in 0..<input.count {
let data = input[i]
if let dataArray = data as? Array<Any> {
outputArray += flatten(input: dataArray)
} else {
outputArray.append(data)
}
}
return outputArray
}
其他几点说明:
Array<Any>
当然等同于[Any]
,因此if
语句可以使用该(通常首选)语法编写,如下所示:
if let dataArray = data as? [Any] {
outputArray += flatten(input: dataArray)
}
此外,如果你只是迭代数组,就没有必要经历整个for i in 0..<input.count { let data = input[i] ...
的考验,如下所示:
func flatten(input: [Any]) -> [Any] {
var outputArray = [Any]()
for data in input {
if let dataArray = data as? [Any] {
outputArray += flatten(input: dataArray)
} else {
outputArray.append(data)
}
}
return outputArray
}