Search This Blog

Thursday, October 19, 2017

Flat nested array recursively in Swift

Following task - make flat array from nested array. Because there are could be any levels of nested array we use recursive approach.

For example - given array [1, [2, [3, 4, 5]]]. We need to get this [1, 2, 3, 4, 5]

Standard Approach

Algorithm
  1. In for loop go through the array
  2. If element of array is int then add it to new array
  3. If element of array is array too then make recursive invoke of function and send this array
We use Any type as type of input array because input array can hold as integers as array. They both are value types, so Any is suitable for us in this function.

Let's get coding.
import UIKit

let array: [Any] = [1, 2, [3]]

func makeFlatArray(_ array: [Any]) -> [Int] {
    var flatArray = [Int]()
    for item in array {
        if let item = item as? Int {
            flatArray.append(item)
        } else if let item = item as? [Any] {
            let result = makeFlatArray(item)
            flatArray += result
        }
    }
    return flatArray
}

print(makeFlatArray([1, 2, 3]))
// [1, 2, 3]
print(makeFlatArray([1, [2, 3, 4]]))
// [1, 2, 3, 4]
print(makeFlatArray([1, [2, [3, 4]]]))
// [1, 2, 3, 4]
print(makeFlatArray([[1], [2, [3, 4, [5]]]]))
// [1, 2, 3, 4, 5]

Using Generics

What if we want to use this function with array of any type. We should use Generics:
func makeFlatArrayGeneric<T>(_ array: [Any]) -> [T] {
    var flatArray = [T]()
    for item in array {
        if let item = item as? T {
            flatArray.append(item)
        } else if let item = item as? [Any] {
            let result: [T] = makeFlatArrayGeneric(item)
            flatArray += result
        }
    }
    return flatArray
}

Now we can use this function with any kind of array. With integer array as previous
let array: [Any] = [1, 2, [3], [4, [5]]]
let items: [Int] = makeFlatArrayGeneric(array)
// [1, 2, 3, 4, 5]

And with array of strings
let array: [Any] = ["A", "BB", ["CCC"], ["DD", ["EE"]]]
let items: [String] = makeFlatArrayGeneric(array)
// ["A", "BB", "CCC", "DD", "EE"]

Make Extension for Array 

What if we want this feature for any array as built in method. Let's create extension for Array Type. Here we use Swift method flatMap.
extension Array {
    
    func makeFlat() -> [Element] {
        let flatArray = self.flatMap { (element) -> [Element] in
            if let array = element as? Array {
                return array.makeFlat()
            }
            return [element]
        }
        return flatArray
    }
}

Result of using array extension.
let array: [Any] = ["A", "BB", ["CCC"], ["DD", ["EE"]]]
print(array.makeFlat())
// ["A", "BB", "CCC", "DD", "EE"]

7 comments:

  1. Really nice article. its really helpful me. Very interesting and good post thanks for sharing such a good blog.
    -Custom Web Design and Development

    ReplyDelete
  2. It was not an easy topic to elaborate in such a short span of time. Custom Website is such a complex topic but you made it easy to understand

    ReplyDelete
  3. This article impresses me with its well-researched material and good writing. I couldn't put this book down since I was so engrossed in it. Your work and skill have impressed me. Thank you a lot. It can be beneficial to those who want to learn more about Best Custom Websites

    ReplyDelete
  4. Thank you for writing this quality informational content.Your writing technique is impressive and enjoyable to read. I'll come back for more fantastic material.
    Best wishes, and good luck.
    Custom Build Website

    ReplyDelete
  5. your article is unbelievable with accurate information. I see a lot of research after that and that is more than I expectedCustom Build Website

    ReplyDelete
  6. Great share!One of the best blogs I have Ever Seen. Keep going!
    iOS App Testing Services

    ReplyDelete
  7. Amazing write-up! The blog was very informative. Keep it up!
    Custom Website/a>

    ReplyDelete