1

I have an array something Like:

let responseArray : [[String : Any]] = [["id": 1, "sub_array": [["id": 2, "sub_array": [["id": 3], ["id": 4]]],["id": 5, "sub_array": [["id": 6], ["id": 7]]]]], ["id": 8, "sub_array": [["id": 9], ["id": 10]]]]
print(responseArray as! NSArray)

and I want to merge it to show in UITableView

expecting the result like :

let expectedOutput : [[String : Any]] = [["id" : 1], ["id" : 2], ["id" : 3], ["id" : 4], ["id" : 5], ["id" : 6], ["id" : 7], ["id" : 8], ["id" : 9], ["id" : 10]]
print(expectedOutput as! NSArray)

I can achieve it by using loops, but how to do it without using a loop?

1
  • Could you please show your way of traversing your nested structure with loops? It's not simple. Commented Mar 31, 2018 at 8:37

2 Answers 2

1

Yes , You can . Swift CollectionTypes (Array , Dictionary , Set) has a massive good methods that provides a many alternative solution in compare of for-loop.

Here it is :-

We will perform 3 tasks as below :

  • First , We will fetch those ids that are not part of sub_array.
  • Second , We will fetch those ids that are the part of sub_array but not the part of inner sub_array.
  • Third and last one , We will fetch those ids that are part of sub_array's inner sub_array.

        let responseArray : [[String : Any]] = [["id": 1, "sub_array": [["id": 2, "sub_array": [["id": 3], ["id": 4]]],["id": 5, "sub_array": [["id": 6], ["id": 7]]]]], ["id": 8, "sub_array": [["id": 9], ["id": 10]]]]
    
        let arrExrernalIds = responseArray.flatMap({$0["id"] as? Int ?? 0})
        print(arrExrernalIds) // output :- [1, 8]
    
        let arrSub_ArrayIDs =   responseArray.flatMap({$0["sub_array"] as? [[String:Any]] ?? []}).flatMap({$0["id"] as? Int ?? 0})
    
        print(arrSub_ArrayIDs) // output :- [2, 5, 9, 10]
    
        let arrSubArray_SubArrayIDs = responseArray.flatMap({$0["sub_array"] as? [[String:Any]] ?? []}).flatMap({$0["sub_array"] as? [[String:Any]] ?? []}).flatMap({$0["id"] as? Int ?? 0})
    
        print(arrSubArray_SubArrayIDs) // output :- [3, 4, 6, 7]
    
        var allIDs = (arrExrernalIds + arrSub_ArrayIDs + arrSubArray_SubArrayIDs).sorted()
    
        print(allIDs) // output :- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    
        var expectedOutput = [[String:Any]]()
    
        for id in allIDs {
            expectedOutput.append(["id":id])
        }
    
        print(expectedOutput) // output :- [["id": 1], ["id": 2], ["id": 3], ["id": 4], ["id": 5], ["id": 6], ["id": 7], ["id": 8], ["id": 9], ["id": 10]]
    

Only 4 Lines of code and you can achieve your desired Array.

Sign up to request clarification or add additional context in comments.

Comments

0

It's certainly possible to write a flatten function for this data structure without explicitly using for a in b loops, but given the nature of your data, loops and recursive calls are IMHO unavoidable.

func flatten(_ array: [[String: Any]]) -> [[String: Any]] {
    var result = [[String: Any]]()

    array.forEach { dict in
        dict.forEach { (key, val) in
            if let v = val as? [[String: Any]] {
                result.append(contentsOf: flatten(v))
            } else {
                result.append([key: val])
            }
        }
    }

    return result
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.