Passing generic array to recursive function

I'm trying to write a simple hand-rolled function to flatten a nested array. My code works fine as a switch statement, but not when I'm recursively calling it within a "for i in 0..arr.count" loop. I look at each element in the passed in array and say "if this is an array, call the function and pass this in, else append to the output array".

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 }


Because my function argument must be of type [Any], I'm forced to pass the "data" variable back into it as [data]. This just forces the function to constantly unpack the array and it just gets stuck in the loop. Any suggestions on how I can avoid this?

Accepted Answer

To prevent the infinite recursion until crash, in line 4, replace:

flatten(input: [data])


with:

flatten(data as! [Any])



Or a total rewrite:

func flatten(_ array: [Any]) -> [Any] {
    var result = [Any]()
    for element in array {
        if let element = element as? [Any] {
            result.append(contentsOf: flatten(element))
        } else {
            result.append(element)
        }
    }
    return result
}


let rosie = [[42, "thirty-nine", 56], "all"] as [Any]
print(flatten(rosie))   // [42, "thirty-nine", 56, "all"]

Thank you so much for this. After watching Dave Abrahms talk on Embracing Algorithms (https://developer.apple.com/videos/play/wwdc2018/223/, I have tried to follow his advice to seek out algorithms before just banging away on the keyboard. I took his advice and found this. Thanks! 🙂

Passing generic array to recursive function
 
 
Q