Reputation: 472
I have two lists of UIViews
, some of that UIViews
have an accessibilityIdentifier
most of them are nil
.
I'm searching for a way to generate a tuple(or something) with the two UIViews
from the lists that have the same accessibilityIdentifier
.
The lists are not sorted or something.
Is there a way to not iterate multiple times through the second list to find every pair?
for view in firstViewList {
if view.accessibilityIdentifier != nil {
for secondView in secondViewList {
if secondView.accessibilityIdentifier != nil && secondView.accessibilityIdentifier == view.accessibilityIdentifier {
viewPairs.append((firstView: view, secondView: secondView))
}
}
}
}
I think this is not very efficient.
Upvotes: 0
Views: 112
Reputation: 51973
This solution creates an array of tuples with views from the first and second list respectively
var viewArray: [(UIView, UIView)]
firstViewList.forEach( { view in
if let identifier = view.accessibilityIdentifier {
let arr = secondViewList.filter( {$0.accessibilityIdentifier == identifier} )
arr.forEach( { viewArray.append((view, $0))})
}
})
Upvotes: 0
Reputation: 63271
Make a dict that indexes both view lists by their ID, filter out the ones where the ID is nil, and then use the keys common to both dicts to create a new dict that indexes pairs of same-id views.
Here's a rough example (which I haven't compiled myself).
func makeDictByAccessibilityID(_ views: [UIView]) -> [AccessibilityID: UIView] {
return Dictionary(uniqueKeysWithValues:
firstViewList
.lazy
.map { (id: $0.accessibilityIdentifier, view: $0) }
.filter { $0.id != nil }
)
}
viewsByAccessibilityID1 = makeDictByAccessibilityID(firstViewList)
viewsByAccessibilityID2 = makeDictByAccessibilityID(secondViewList)
commonIDs = Set(viewsByAccessibilityID1.keys).intersecting(
Set(viewsByAccessibilityID2.keys)
)
let viewPairsByAccessibilityID = Dictionary(uniqueKeysWithValues:
commonIDs.lazy.map { id in
// Justified force unwrap, because we specifically defined the keys as being available in both dicts.
(key: id, viewPair: (viewsByAccessibilityID1[id]!, viewsByAccessibilityID2[id]!))
}
}
This runs in O(n) time, which is the best you can get for this problem.
Upvotes: 1
Reputation: 331
I think you should first filtered your two arrays from the nil value then you can do like this
let tempfirstViewList = firstViewList.filter { (view) -> Bool in
view.accessibilityIdentifier != nil
}
var tempsecondViewList = secondViewList.filter { (view) -> Bool in
view.accessibilityIdentifier != nil
}
tempfirstViewList.forEach { (view) in
let filterdSecondViewList = tempsecondViewList.filter { (secondView) -> Bool in
secondView.accessibilityIdentifier == view.accessibilityIdentifier
}
if let sView = filterdSecondViewList.first {
viewPairs.append((firstView: view, secondView: sView))
//after add it to your tuple remove it from the temp array to not loop throw it again
if let index = tempsecondViewList.firstIndex(of: sView) {
tempsecondViewList.remove(at: index)
}
}
}
Upvotes: 0