Find whether two Swift Arrays contain the same elements

前端 未结 3 549
清歌不尽
清歌不尽 2020-12-22 11:41

I have two arrays

let a1 = [obj1, obj2, obj3]
let a2 = [obj3, obj2, obj1]

Assume that the array elements are custom objects which are

相关标签:
3条回答
  • 2020-12-22 11:53

    If the items are unique and equatable (as in your example), convert to a Set and compare the Sets:

    let a1 = [1, 2, 3]
    let a2 = [3, 2, 1]
    Set(a1) == Set(a2)
    

    With some futzing, this can be made to work for an arbitrary class:

    class Person : NSObject {
        let name: String
        init(name:String) {self.name = name}
        override func isEqual(other: AnyObject?) -> Bool {
            return other is Person && (other as! Person).name == self.name
        }
        override var hashValue : Int {
            return self.name.hashValue
        }
    }
    
    let a1 = [Person(name:"Matt"), Person(name:"Sam")]
    let a2 = [Person(name:"Sam"), Person(name:"Matt")]
    Set(a1) == Set(a2)
    
    0 讨论(0)
  • 2020-12-22 12:10

    These 2 solutions also work if the arrays have duplicates.

    Scenario 1: elements are sortable

    let a1 = [1, 2, 3]
    let a2 = [3, 2, 1]
    
    let equals = a1.sorted() == a2.sorted()
    

    Time Complexity: We need to sort both arrays so time complexity is O(n * log n) + O( m * log m)

    Space complexity: A temporary copy of both arrays is created so the required space is O(n) + O (m).

    Where n is the number of elements in a1 and m is the number of elements in a2.

    Scenario 2: elements are NOT sortable

    func equals<Element:Equatable>(listA:[Element], listB:[Element]) -> Bool {
        guard listA.count == listB.count else { return false }
    
        var listB = listB
    
        for a in listA {
            if let indexB = listB.indexOf(a) {
                listB.removeAtIndex(indexB)
            } else {
                return false
            }
        }
    
        return listB.isEmpty
    }
    

    Time Complexity: We are iterating the first array and each time we perform a linear search into the second array so O(n * m)

    Space Complexity: We created a copy of the second array so O(m)

    0 讨论(0)
  • 2020-12-22 12:12

    You can convert them into Set or NSSet instances which are unsorted by definition and compare those. Better yet, instead of using arrays at all, consider using sets in the first place.

    let a1 = [1, 4, 5]
    let a2 = [4, 5, 1]
    let s1 = NSSet(array: a1)
    let s2 = NSSet(array: a2)
    print(s1 == s2) // Prints "true"
    

    If objects may appear multiple times in your arrays, you need to use a NSCountedSet instead which also counts how often each object occurs in a set:

    let a1 = [1, 1, 2]
    let a2 = [1, 2, 2]
    
    let s1 = NSSet(array: a1)
    let s2 = NSSet(array: a2)
    print(s1 == s2) // Prints "true"
    
    let c1 = NSCountedSet(array: a1)
    let c2 = NSCountedSet(array: a2)
    print(c1 == c2) // Prints "false"
    
    0 讨论(0)
提交回复
热议问题