简体   繁体   中英

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

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 :)

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 newDict prints:

[2: ["vegetable": ["carrot"]], 3: ["meat": ["steak", "pork"]], 1: ["fruit": ["apple"]]]

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"]

在此输入图像描述

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"])
]

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"]]]

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")
    }
  }
}
 }
}  

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