Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/111.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 使用Firebase和Swift 3比较值的结构数据_Ios_Swift_Firebase_Firebase Realtime Database - Fatal编程技术网

Ios 使用Firebase和Swift 3比较值的结构数据

Ios 使用Firebase和Swift 3比较值的结构数据,ios,swift,firebase,firebase-realtime-database,Ios,Swift,Firebase,Firebase Realtime Database,我想知道我构造数据的方式是否是最好的方法。我之所以想知道这一点,是因为我需要从数据中获得复杂的需求 我试图检查用户的配料列表是否与配方配料列表匹配,并能够显示和计算它们。例如: 成分计数 1/2成分 用户拥有 面团 用户没有 Mozzarella “我的食谱”的数据结构当前如下所示: { "RecipeData": { "-KlKMkBekJ6plrXI5cZV": { "name": "Pizza", "ingredients": { "-K

我想知道我构造数据的方式是否是最好的方法。我之所以想知道这一点,是因为我需要从数据中获得复杂的需求

我试图检查用户的配料列表是否与配方配料列表匹配,并能够显示和计算它们。例如:

成分计数

1/2成分

用户拥有

面团

用户没有

Mozzarella

“我的食谱”的数据结构当前如下所示:

{
  "RecipeData": {
    "-KlKMkBekJ6plrXI5cZV": {
      "name": "Pizza",
      "ingredients": {
        "-KkY8kL_wvxrcqMn_aP_": true,
        "-KkbS1pYW_9l4y4HPuog": true
      }
    }
  }
}
成分的详细信息,即名称取自字典:

{
  "IngredientData": {
    "ingredients": {
      "-KkbS1pYW_9l4y4HPuog": {
        "name": "Dough"
      },
      "-KkY8kL_wvxrcqMn_aP_": {
        "name": "Mozzarella"
      }
    }
  }
}
以下是用户添加自己的配料时的外观:

{
  "users": {
    "Ss5XNpWJ5IfIuYiMqsxTnMgjNrm1": {
      "usersList": {
        "-KlKuq2xjbQcR3ZMsHF1": {
          "name": "Dough"
        }
      }
    }
  }
}
有了这个数据结构,我发现很难将用户的配料表的值与配方的配料表进行比较

更新: 我有一个
配料
类来处理用户配料中的属性,在获取配方中配料的名称时,我也使用该类:

class Ingredient {

    var name: String?
    var key: String?

    init(from snapshot: FIRDataSnapshot) {
        let snapshotValue = snapshot.value as? [String: Any]

        self.key = snapshot.key
        self.ref = snapshot.ref
        self.name = snapshotValue?["name"] as? String
    }
我还有一个
IngredientManager
,里面有一系列成分,我可以在任何地方调用它

我有一个
Recipe
类,它处理配方中的属性:

class Recipe {

    var name: String!
    var ingredients = [String]()
    var key: String


    init(from snapshot: FIRDataSnapshot) {

        let snapshotValue = snapshot.value as! [String: Any]

        self.name = snapshotValue["name"] as? String
        self.key = snapshot.key

        recipeIng(snapshot: snapshot.childSnapshot(forPath: "ingredients"))


    }
    // Function to count the number of ingredients inside recipe... this works
    func recipeIng(snapshot: FIRDataSnapshot) {

        for item in snapshot.children {

            guard let ing = item as? FIRDataSnapshot else { continue }
            // Gets the key and turns it into a string and then appends it to the array.
            guard let value = ing.key as? String else { return }

            ingredients.append(value)
        }
    }


    // Function to match the ingredients.
    func matchedIngredients() -> ([String], [String]) {

        var userHas = [String]()
        var userHasNot = [String]()

        // loops through the users ingredients
        for ingedient in IngredientManager.shared.ingredients {
            // loops through the recipe's ingredients
            for i in ingredients {

                if ingedient.name == r {
                    userHas.append(i)
                } else {
                   userHasNot.append(i)
                }
            }
        }
        return (userHas, userHasNot)
    }
}
我能够计算配方中的配料数量,但现在我很难将其与用户的配料列表进行比较<代码>成分。名称能够获取用户的名称成分,这是我想用来比较的,因为用户的关键成分与配方完全不同

这是我在标签上显示它的方式:

ingredientLbl.text = "\(recipe.matchedIngredients().0.count)/\(recipe.ingredients.count)"

由于额外的查找,这就有点像嵌套练习。但如果你通读这些循环,其实并不难。在JavaScript中,这样做的诀窍是:

ref.child(“用户”)。一次(“值”)。然后((usersSnapshot)=>{
usersSnapshot.forEach((userSnapshot)=>{
参考子项(“RecipeData”)。一次(“值”)。然后((配方快照)=>{
recipesSnapshot.forEach((recipeSnapshot)=>{
var userNeeds=[];
recipeSnapshot.child(“配料”).forEach((RecipeIngCreditSnapshot)=>{
userNeeds.push(ingredientsData[recipeIngredientSnapshot.key].name);//假设用户需要此
var recipeIngredientName=ingredientsData[recipeIngredientSnapshot.key];
userSnapshot.child(“usersList”).forEach((userIngredientSnapshot)=>{
var index=userNeeds.indexOf(userIngredientSnapshot.val().name)
如果(索引>=0){
用户需求.拼接(索引,1);
}
});
console.log(“用户”+userSnapshot.key+”+(userNeeds.length?“cannot”:“can”)+“make”+recipeSnapshot.key+“:缺少的成分”+userNeeds);
});
});
});
});
});
工作jsbin:


我在这里所做的不同之处在于,我首先假设用户没有每个必要的成分,然后如果发现他们已经有了这些成分,就取消这个假设。

由于额外的查找,这有点像嵌套练习。但如果你通读这些循环,其实并不难。在JavaScript中,这样做的诀窍是:

ref.child(“用户”)。一次(“值”)。然后((usersSnapshot)=>{
usersSnapshot.forEach((userSnapshot)=>{
参考子项(“RecipeData”)。一次(“值”)。然后((配方快照)=>{
recipesSnapshot.forEach((recipeSnapshot)=>{
var userNeeds=[];
recipeSnapshot.child(“配料”).forEach((RecipeIngCreditSnapshot)=>{
userNeeds.push(ingredientsData[recipeIngredientSnapshot.key].name);//假设用户需要此
var recipeIngredientName=ingredientsData[recipeIngredientSnapshot.key];
userSnapshot.child(“usersList”).forEach((userIngredientSnapshot)=>{
var index=userNeeds.indexOf(userIngredientSnapshot.val().name)
如果(索引>=0){
用户需求.拼接(索引,1);
}
});
console.log(“用户”+userSnapshot.key+”+(userNeeds.length?“cannot”:“can”)+“make”+recipeSnapshot.key+“:缺少的成分”+userNeeds);
});
});
});
});
});
工作jsbin:


我在这里所做的不同之处在于,我首先假设用户没有每种必要的成分,然后如果他们已经有了这些成分,就取消这个假设。

我觉得这很好。如果你表现出你所做的尝试,可能会更容易得到帮助。我希望在一个列表上有一个循环,在这个循环中,如果两个列表中都存在项,则从两个列表中删除该项。循环结束时,列表应该都是空的。@FrankvanPuffelen请查看我的更新答案,如果你想让我告诉你如何获得配方中每种成分的名称,我只是不想让你觉得我只是发布了很多代码。我想你问题的症结在于你的最后一句话:“对于用户来说,关键的成分与配方完全不同“。为了比较成分,你真的应该对它们使用相同的键。它也可以基于比较名称来工作,但是代码将更难阅读/维护。我感觉这就是问题所在。我想知道你是否可以指导我让用户添加与配方成分具有相同键的成分。目前,我不得不手动将配料添加到配方中,即“-KkbS1pYW_9l4y4HPuog”:true”。我不知道如何将配料字典中的配料添加到用户列表中。如果这个问题与这篇文章的初始问题无关,那么我将在其他地方问它。我觉得这个问题很好。如果你表现出你所做的尝试,可能会更容易得到帮助。我希望在一个列表上有一个循环,在这个循环中,如果两个列表中都存在项,则从两个列表中删除该项。最后