Created
March 20, 2017 22:26
-
-
Save matnogaj/3f3ffb10d7393a585faac25bf49f1655 to your computer and use it in GitHub Desktop.
Dictionary differences
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
import CoreData | |
var dictA: [String : Any] = ["key1": "value1", "key3": "value3", "key4": "notModified", | |
"key5" : 1, "key6" : 1.0, | |
"key7": ["a", "b"], "key8": ["a"], "key9": ["a", "b"]] | |
var dictB: [String : Any] = ["key2": "value2", "key3": "modified", "key4": "notModified", | |
"key5" : 2, "key6" : 2.0, | |
"key7": ["a", "c"], "key8": ["a", "b"], "key9": ["a"]] | |
public extension Dictionary { | |
public func differences(_ other: Dictionary) -> (inserted: Dictionary, removed: Dictionary, updated: Dictionary) { | |
var inserted = self.filter { other[$0.key] == nil } | |
var removed = other.filter { self[$0.key] == nil } | |
let correctUpdated: [(key: Key, value: Value)] = self.flatMap { | |
guard let otherValue = other[$0.key] else { return nil } | |
switch ($0.value, otherValue) { | |
case (let a as String, let b as String): if a != b { return $0 } | |
case (let a as Int, let b as Int): if a != b { return $0 } | |
case (let a as Double, let b as Double): if a != b { return $0 } | |
case (let a as NSManagedObject, let b as NSManagedObject): if a.objectID != b.objectID { return $0 } | |
case (let a as Array<Any>, let b as Array<Any>): | |
let insertedToArray = a.filter({ element in | |
guard let stringElement = element as? String else { return false } | |
return !b.contains(where: { otherElement in | |
guard let otherStringElement = otherElement as? String else { return false } | |
return stringElement == otherStringElement | |
}) | |
}) | |
let removedFromArray = b.filter({ element in | |
guard let stringElement = element as? String else { return false } | |
return !a.contains(where: { otherElement in | |
guard let otherStringElement = otherElement as? String else { return false } | |
return stringElement == otherStringElement | |
}) | |
}) | |
if !removedFromArray.isEmpty { | |
removed.append((key: $0.key, value: removedFromArray as! Value)) | |
} | |
if !insertedToArray.isEmpty { | |
inserted.append((key: $0.key, value: insertedToArray as! Value)) | |
} | |
return nil | |
case (let a as NSSet, let b as NSSet): | |
let insertedToSet = a.filter({ element in | |
guard let managedElement = element as? NSManagedObject else { return false } | |
return !b.contains(where: { otherElement in | |
guard let otherManagedElement = otherElement as? NSManagedObject else { return false } | |
return managedElement.objectID == otherManagedElement.objectID | |
}) | |
}) | |
let removedFromSet = b.filter({ element in | |
guard let managedElement = element as? NSManagedObject else { return false } | |
return !a.contains(where: { otherElement in | |
guard let otherManagedElement = otherElement as? NSManagedObject else { return false } | |
return managedElement.objectID == otherManagedElement.objectID | |
}) | |
}) | |
if !removedFromSet.isEmpty { | |
removed.append((key: $0.key, value: removedFromSet as! Value)) | |
} | |
if !insertedToSet.isEmpty { | |
inserted.append((key: $0.key, value: insertedToSet as! Value)) | |
} | |
return nil | |
default: return nil | |
} | |
return nil | |
} | |
var insertedDict: Dictionary = [:] | |
inserted.forEach { insertedDict[$0.key] = $0.value } | |
var removedDict: Dictionary = [:] | |
removed.forEach { removedDict[$0.key] = $0.value } | |
var updatedDict: Dictionary = [:] | |
correctUpdated.forEach { updatedDict[$0.key] = $0.value } | |
return (insertedDict, removedDict, updatedDict) | |
} | |
} | |
let (inserted, removed, updated) = dictB.differences(dictA) | |
print("inserted: \(inserted)") | |
print("removed: \(removed)") | |
print("updated: \(updated)") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment