Parsing array hierarchy


My notes on parsing a data hierarchy when UITesting.Code for finding an illusive element in a UI-structure

let dimensionalArray: [Any] = [["a"], [["b", "c"], ["d", "e", "f"]], "g", "h"]
// print(dimensionalArray[0])
// print(dimensionalArray[1])
// print(((dimensionalArray[1] as! Array<Any>)[1]as! Array<Any>)[1] )
func element(root: [Any], index: [Int]) -> Any? {
   let children = root
   if index.count == 0 { return root }/*returns the root*/
   else if (index.count == 1 && children.count >= index[0]) { return children[index[0]]}/*the index is at its end point, cut of the branch*/
   else if (index.count > 1 && children.count > 0) {
      let newIndex = Array(index[1..<index.count])
      if let childArr: [Any] = children[index[0]] as? Array<Any> {
         return element(root:childArr, index:newIndex)
      } else {
         return nil
      }
   } /*here is where the recursive magic happens*/
   return nil
}
print(element(root: dimensionalArray, index: [1,0,1]))

Ancestry method for UITesting:

public typealias MatchCondition = (_ element: XCUIElement) -> Bool
   /**
    * Returns an array of ancestral elements (alt name: heritage)
    * - Parameter condition: a closure that evaluates to true or false
    * - Parameter element: the point to search from
    * ## Example:
    * let imgElement = XCUIApplication().descendants(matching: .image).firstMatch
    * let condition: ElementParser.MatchCondition = { element in element.screenshot().image.size == CGSize(width: 200, height: 50)) }
    * let ancestry: [XCUIElement]? = ElementParser.ancestry(element: imgElement, condition: condition)
    * let ImgElementParent: XCUIElement? = ancestry?.last
    * - Fixme: ⚠️️ Refactor with .map or .flatMap on this method when u have time
    */
   public static func ancestry(root: (index: Int, element: XCUIElement), condition: MatchCondition) -> [(Int, XCUIElement)]? {
      var collector: [(Int, XCUIElement)]? = nil
      let children: [XCUIElement] = root.element.children(matching: .any).allElementsBoundByIndex
      Swift.print("children.count:  \(children.count)")
      for (i, child) in children.enumerated() {
         let metCondition: Bool = condition(child)
         Swift.print("metCondition:  \(metCondition)")
         if metCondition {
            collector = [(i, child)] // Found the item, we don't include the actual item we are looking for
            break
         } else if let descendants = ancestry(root: (0, child), condition: condition) { // try to traverse the descendants
            collector = [(i, child)] + descendants
            break
         } // else {
            // collector = nil // dead end, return nil all the way up to the caller
         // }
      }
      return collector
   }

Resources: