How do i compare two dictionaries in swift and then append any similarities to a new dictionary?

Question

i know this might seem like a confusing question so here's my scenario... I have two dictionaries and i need to organise them into one dictionary where the keys from both of the initial 2 dictionaries share the same values from the keys that are the same from the starting 2 dictionaries. Example:

var dict1 = [1: "fruit", 2: "vegetable", 3: "meat"]
var dict2 = [2: "carrot", 3: "steak", 1: "apple", 3: "pork"] 
var newDict = [1: ["fruit": ["apple"]], 2: ["vegetable": ["carrot"]], 3: ["meat": ["steak, pork"]]]

So its organised where each category (fruit, veg, meat) has a unique id (Int), and in that category is an array of values appropriate for that category. The end result is that i'm hoping to populate a table view with this data using the category's as section headers and the array of values for that sections data.

Any help is much appreciated. Thanks :)


Show source
| sorting   | swift   | uitableview   | arrays   | dictionary   2017-01-05 10:01 4 Answers

Answers to How do i compare two dictionaries in swift and then append any similarities to a new dictionary? ( 4 )

  1. 2017-01-05 11:01

    This may be help for you

     var dict1 = [(0, ["sender": "user1", "time": NSDate(), "mId": "as2f2ASf"]), (1, ["sender": "user1", "time": NSDate(), "mId": "Sjf82FsJ"])]
    
     var dict2 = [(0, ["sender": "user2", "time": NSDate(), "mId": "J2fAS92D"]), (1, ["sender": "user2", "time": NSDate(), "mId": "Sjf82FsJ"])]
    
    
    var dict3 = [[0: ["sender": "user1", "time": NSDate(), "mId": "as2f2ASf"]], [1: ["sender": "user1", "time": NSDate(), "mId": "Sjf82FsJ"]]]for (_,value1) in dict1 {
    
    
     if let mld1 = value1["mId"] {
    for(_,value2) in dict2 {
      if let mld2 = value2["mId"] {
        if mld1 == mld2 {
          println("Found diff")
        }
      }
    }
     }
    }  
    
  2. 2017-01-05 11:01

    As I said in the comment, your second dictionary has duplicate keys, so it's not valid Swift.

    Assuming you solve the duplicate key issue by replacing the duplicate with a new one, unique this time, here is a quick algorithm almost achieving what you want.

    let dict1 = [1: "fruit", 2: "vegetable", 3: "meat"]
    let dict2 = [2: "carrot", 3: "steak", 1: "apple", 4: "pork"]
    
    var newDict = [Int:[String:[String]]]()
    
    for category in dict1 {
        if let existingCat = newDict[category.key] {
    
        } else {
            let newCat = [category.value: [dict2[category.key]!]]
            newDict[category.key] = newCat
        }
    }
    
    print (newDict)
    

    It won't give you the list of products you want though, so I've changed your input data types to something more suitable (I'm not saying it's optimal, but it works):

    let input1 = [(1, "fruit"), (2, "vegetable"), (3, "meat")]
    let input2 = [(2, "carrot"), (3, "steak"), (1, "apple"), (3, "pork")]
    
    var newDict = [Int:[String:[String]]]()
    
    for category in input1 {
        newDict[category.0] = [category.1:[]]
    }
    
    for meal in input2 {
        if let existingCat = newDict[meal.0]?.first {
            newDict[meal.0] = [existingCat.key: existingCat.value + [meal.1]]
        }
    }
    
    print (newDict)
    

    At the end newDictprints:

    [2: ["vegetable": ["carrot"]], 3: ["meat": ["steak", "pork"]], 1: ["fruit": ["apple"]]]
    
  3. 2017-01-05 12:01

    If you correct your dictionaries to:

    let dict1 = [1: "fruit", 2: "vegetable", 3: "meat"]
    var dict2 = [2: ["carrot"], 1: ["apple"], 3: ["pork", "steak"]]
    

    you could reduce it with

    let result = dict1.keys.reduce([Int: [String: [String]]]()) { (result, key) in
        var result = result
        result.updateValue([dict1[key]!: dict2[key] ?? []], forKey: key)
        return result
    }
    

    which would result in [2: ["vegetable": ["carrot"]], 3: ["meat": ["pork", "steak"]], 1: ["fruit": ["apple"]]]

  4. 2017-01-05 14:01

    Your code does not compile

    As @Bogdan Farca noted in the comments your second dictionary won't compile because of duplicate key

    let dict2 = [2: "carrot", 3: "steak", 1: "apple", 3: "pork"]
    

    enter image description here

    A better way to represent the information of dict2 is using the food name as key and the category ID as value

    let dict2 = ["carrot" : 2,"steak": 2,"apple": 1, "pork":3]
    

    I am assuming the food names to be unique.

    Better names

    In order to make the code more readable we should also use better names so

    let categories = [1: "fruit", 2: "vegetable", 3: "meat"]
    let foods = ["carrot" : 2, "steak": 3, "apple": 1, "pork":3]
    

    Using a Model

    We can finally focus on the solution. You want as output something like this [Int : Dictionary<String, Array<String>>]

    It's a complex combination of dictionaries/arrays, why don't you simply use a model value?

    struct FoodCategory {
        let categoryID: Int
        let categoryName: String
        let foods: [String]
    }
    

    Now you can just write

    let foodCategories = categories.map { cat -> FoodCategory in
        let foodNames = foods.filter { $0.value == cat.key }.map { $0.0 }
        return FoodCategory(categoryID: cat.key, categoryName: cat.value, foods: foodNames )
    }
    

    And this is the result

    [
        FoodCategory(categoryID: 2, categoryName: "vegetable", foods: ["carrot"]),
        FoodCategory(categoryID: 3, categoryName: "meat", foods: ["pork", "steak"]),
        FoodCategory(categoryID: 1, categoryName: "fruit", foods: ["apple"])
    ]
    

Leave a reply to - How do i compare two dictionaries in swift and then append any similarities to a new dictionary?

◀ Go back