15

I have a class A:

class A {
   var identifier: String?
   var quantity: Int = 0
}

Two arrays of A instances:

var array1: [A] = [a1, a2, a3, a4]
var array2: [A] = [a5, a6, a7, a8]

I don't know which is the best way to check: array1==array2 if a1.identifier == a5.identifier, a2.identifier == a6.identifier, a3.identifier==a7.identifier, a4.identifier==a8.identifier in Swift.

Please help me...

9
  • array1 and array2 will always be of the same size? show array count be a check also? or check should be on properties of each element in arrays? Commented Aug 26, 2016 at 7:57
  • @ddb: sorry, their counts are random Commented Aug 26, 2016 at 7:59
  • so if they have different counts, they should be classified as unequal, right? Commented Aug 26, 2016 at 8:00
  • What do you consider equal? If they have the same length? If they have the same items? Do the items all have to be at the same index? Commented Aug 26, 2016 at 8:02
  • @ddb: ya... I got it, but how about another case @-@ Commented Aug 26, 2016 at 8:02

7 Answers 7

27

You can try like this:

let result = zip(array1, array2).enumerated().filter() {
    $1.0 == $1.1
}.map{$0.0}
Sign up to request clarification or add additional context in comments.

4 Comments

@Rahul Tripathi, dear Rahul Tripathi can you please explain your code. It's interesting, but I can't understood.This is my code let array1: [Int] = [1, 2, 3, 4] let array2: [Int] = [5, 6, 7, 8] let result = zip(array1, array2).enumerated().filter() { $1.0 == $1.1 }.map{$0.0} print(result)
Event if this works, it looks like a copy paste code from somewhere without any explanation of the code!.@Rahul Tripathi
I do not think this is a good solution. It only works for one scenario i.e. when the two arrays are sorted in the same sequence.
It is an incorrect answer because [1,2,3] is equal to [1,2,3,4] with this comparison (zip chooses the length of the shortest array)
18

Swift 4

The following method makes it much more easy.

Method 1 - Using Equatable Protocol

Step1 - Make your class 'A' equatable as follows

extension A: Equatable {
    static func ==(lhs: A, rhs: A) -> Bool {
        // Using "identifier" property for comparison
        return lhs.identifier == rhs.identifier
    }
}

Step2 - Sort your arrays in ascending or descending order

let lhsArray = array1.sorted(by: { $0.identifier < $1.identifier })
let rhsArray = array2.sorted(by: { $0.identifier < $1.identifier })

Step3 - Use == or elementsEqual comparison

let isEqual = lhsArray == rhsArray

OR

let isEqual = lhsArray.elementsEqual(rhsArray, by: { $0 == $1} )

Method 2 (Without Equatable Protocol)

Step 1 - Sort Array as described in Method1, step 2

Step 2 - Use elementsEqual

lhsArray.elementsEqual(rhsArray, by: { $0.identifier == $1.identifier })

Read more about Array Comparison here

5 Comments

elementsEqual is a great little function, never come across it before but it's exactly what I needed :)
Thank you for your response @Anand . But if I want to create new array with just equal objects for how can I do?
@ErkamKUCET you can use array.filter method.
@Anand Okay, Actually, my problem is that I have two arrays of the same type and I want to create a new array with the same ones from among these arrays.
@ErkamKUCET: You should go through official doc. There are many built in functions are available which you can make use of. If you still couldn't find the right method, ask it as a new question here.
9

Assume your data like that:

struct Person
    {
        let name: String
        let id:  Int
    }

    var people1 = [
        Person(name: "Quang Hà", id: 42),
        Person(name: "Lý Hải", id: 23),
        Person(name: "Maria", id: 99)
    ]

    var people2 = [
        Person(name: "Maria yyy", id: 99),
        Person(name: "Billy", id: 42),
        Person(name: "David", id: 23)
    ]

This is the method to compare two arrays of people with id:

func areArrayPeopleEqual(people1:[Person], people2: [Person]) -> Bool {
    var array1 = people1
    var array2 = people2

    // Don't equal size => false
    if array1.count != array2.count {
        return false
    }

    // sort two arrays
    array1.sortInPlace() { $0.id > $1.id }
    array2.sortInPlace() {$0.id > $1.id }

    // get count of the matched items
    let result = zip(array1, array2).enumerate().filter() {
        $1.0.id == $1.1.id
        }.count

    if result == array1.count {
        return true
    }

    return false
}

1 Comment

There is no reason to use .enumerate() to get count of the matched items, but then filter will looks like { $0.0.id == $0.1.id }
5

This method could be used if you have some parameter to compare:

let difference = currentObjects
    .filter({ currentObject in
        !(newObjects
            .contains(where: { $0.identifier == currentObject.identifier }))
    })

Comments

4

I found this really easy solution at https://www.hackingwithswift.com/example-code/language/how-to-find-the-difference-between-two-arrays

extension Array where Element: Hashable {
func difference(from other: [Element]) -> [Element] {
    let thisSet = Set(self)
    let otherSet = Set(other)
    return Array(thisSet.symmetricDifference(otherSet))
 }
}

let names1 = ["a1", "A4", "a3", "a4"]//["John", "Paul", "Ringo"]
let names2 = ["a1", "a5", "a4","a1.1"]//["Ringo", "George"]
let difference = names1.difference(from: names2)

Comments

3

First we extend Equatable class, to have a DRY code, than if the 2 arrays are always of the same size, or if at least the first one is <= than the second you can go with this solution.

Pay attention that you are working with optionals, you may have to unwrap them before.

class A {
    var identifier: String?
    var quantity: Int = 0

    init(identifier: String, quantity: Int) {
        self.identifier = identifier
        self.quantity = quantity
    }
}

let a1: A = A(identifier: "1", quantity: 1)
let a2: A = A(identifier: "2", quantity: 2)
let a3: A = A(identifier: "3", quantity: 3)
let a4: A = A(identifier: "4", quantity: 4)

let a5: A = A(identifier: "1", quantity: 1)
let a6: A = A(identifier: "2", quantity: 2)
let a7: A = A(identifier: "3", quantity: 3)
let a8: A = A(identifier: "4", quantity: 4)

var array1: [A] = [a1, a2, a3, a4]
var array2: [A] = [a5, a6, a7, a8]

func areEquals(array1: [A], array2: [A]) -> Bool {
    if array1.count < array2.count {
        return false
    }
    for i in 0...array2.count - 1 {
        if array1[i] != array2[i] {
            return false
        }
    }
    return true
}


extension A: Equatable {
    static func ==(lhs: A, rhs: A) -> Bool {
        //you can choose how and when they should be equals
        return lhs.identifier == rhs.identifier
    }
}

Proof of working

Comments

1

try this code, let me know if it works

func toDictionary<E, K, V>(
    array:       [E],
    transformer: (element: E) -> (key: K, value: V)?)
    -> Dictionary<K, V>
{
    return array.reduce([:]) {
        (var dict, e) in
        if let (key, value) = transformer(element: e)
        {
            dict[key] = value
        }
        return dict
    }
}

then you can execute a check like below

let areEqual = array1.count == array2.count;
if areEqual {
    let dict1 = toDictionary(array1) { ($0.identifier, $0.quantity) }
    let dict2 = toDictionary(array2) { ($0.identifier, $0.quantity) }
    areEqual = NSDictionary(dictionary: dict1).isEqualToDictionary(dict2)
}
print(areEqual)

disclaimer: function toDictionary has been took form here

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.