简体   繁体   中英

Compare the content of two arrays in swift

I have an array that I have to cut, on the first 3, 7 or 30 entries.

Then I have an ArraySlice which I want to pack into an array.

Now if I want to compare the new array I created from the ArraySlice with another array (if both have the same content) I always get false as the result.

I believe it is due to the newly created Array from the ArraySlice.

What can I do so that the result is not always false. the content is the same, have checked it with print (...)

extension Date {
    static func compareLastDays (compareArray: [Date]) -> Bool{

        var compareArray2: [Date] = []
        var createDateArray: [Date] = []

        var days = compareArray.count

        if days >= 30 {
            days = 30
            let arraySlice =  compareArray.prefix(days)
            compareArray2 = Array(arraySlice)
        }
        else if days >= 7{
            days = 7
            let arraySlice = compareArray.prefix(days)
            compareArray2 = Array(arraySlice)
        }
        else {
            days = 3
            let arraySlice = compareArray.prefix(days)
            compareArray2 = Array(arraySlice)
        }

        let startDate = Date.init()
        var endDate = Calendar.current.date(byAdding: .day, value: -days, to: startDate)!

        print("startDate", startDate)
        print("endDate", endDate)


        while startDate > endDate{
            createDateArray.insert(endDate, at: 0)
            guard let newDate = Calendar.current.date(byAdding: .day, value: 1, to: endDate) else {
                break
            }
            print("extension new Date", newDate)
            endDate = newDate
        }
        print(compareArray2, "extension compareArray")
        print(createDateArray, "extension createDateArray")


        if createDateArray == compareArray2 {
            print("Compare ARRAY true", createDateArray, compareArray2)
            return true
        }
        else {
            print("Compare ARRAY false", createDateArray, compareArray2)
            return false
        }

    }
}

print statements:

    startDate 2019-07-28 19:00:22 +0000 
    endDate 2019-07-21 19:00:22 +0000 
    extension new Date 2019-07-22 19:00:22 +0000 
    extension new Date 2019-07-23 19:00:22 +0000
    extension new Date 2019-07-24 19:00:22 +0000 
    extension new Date 2019-07-25 19:00:22 +0000 
    extension new Date 2019-07-26 19:00:22 +0000 
    extension new Date 2019-07-27 19:00:22 +0000 
    extension new Date 2019-07-28 19:00:22 +0000 

[2019-07-27 19:00:22 +0000, 2019-07-26 19:00:22 +0000, 2019-07-25 19:00:22 +0000, 2019-07-24 19:00:22 +0000, 2019-07-23 19:00:22 +0000, 2019-07-22 19:00:22 +0000, 2019-07-21 19:00:22 +0000] extension compareArray 
[2019-07-27 19:00:22 +0000, 2019-07-26 19:00:22 +0000, 2019-07-25 19:00:22 +0000, 2019-07-24 19:00:22 +0000, 2019-07-23 19:00:22 +0000, 2019-07-22 19:00:22 +0000, 2019-07-21 19:00:22 +0000] extension createDateArray 
Compare ARRAY false [2019-07-27 19:00:22 +0000, 2019-07-26 19:00:22 +0000, 2019-07-25 19:00:22 +0000, 2019-07-24 19:00:22 +0000, 2019-07-23 19:00:22 +0000, 2019-07-22 19:00:22 +0000, 2019-07-21 19:00:22 +0000] [2019-07-27 19:00:22 +0000, 2019-07-26 19:00:22 +0000, 2019-07-25 19:00:22 +0000, 2019-07-24 19:00:22 +0000, 2019-07-23 19:00:22 +0000, 2019-07-22 19:00:22 +0000, 2019-07-21 19:00:22 +0000]

One way to solve this is to extract some of the date components for the dates and then compare the components.

The below code will fail when comparing the dates directly but succeed when comparing the components which goes from year down to seconds

let now = Date()
let now2 = Date()
print(now == now2 ) // -> false

let components1 = Calendar.current.dateComponents([.year,.month,.day,.hour,.minute, .second], from: now)
let components2 = Calendar.current.dateComponents([.year,.month,.day,.hour,.minute, .second], from: now2)
print(components1 == components2) // -> true

To make the code clearer the set of components can be made into a constant

let compareSet:Set<Calendar.Component> = [.year, .month, .day, .hour, .minute, .second]

A similar solution to this could be to use a DateFormatter and compare the strings. Both offers the possibility to easily set the precision used when comparing dates

Here is a way to do with a DateFormatter but in this example the comparison is only done down to minutes

let df = DateFormatter()
df.dateStyle = .full
df.timeStyle = .short
print(df.string(from: now) == df.string(from: now2))

Of course for either solution the arrays can't be compared directly and instead they need to be looped over and each component needs to be compared individually to the component in the other array

Below is an example using the date formatter solution

guard compareArray2.count == createDateArray.count else { return false}
for i in 0..<compareArray2.count {
    if df.string(from: compareArray2[i]) != df.string(from: createDateArray[i]) {
        return false
    }
}
return true

since the code is tricky and you said it doesn't work which it should, i found you this work around:

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

        if arr.count == 0{
            return true
        }else{
            return false
        }
    }
}

let date1 = Date()
let date2 = Date()
let date3 = Date()
let arr1 = [date1,date2,date3]
let arr2 = [date1,date2]

arr1.isSame(from: arr2)

if the 2 arrays are the same, it return true, else false.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM