我想知道我的数据结构方式是否是最好的方法。我之所以想知道这是因为我需要从数据中获得复杂的要求。
我正在尝试检查用户成分列表是否与食谱成分列表相匹配,并能够显示和计算它们。例如:
成分计数
1/2 ingredients
用户
Dough
用户没有
Mozzarella
我的食谱的数据结构目前如下所示:
{
"RecipeData": {
"-KlKMkBekJ6plrXI5cZV": {
"name": "Pizza",
"ingredients": {
"-KkY8kL_wvxrcqMn_aP_": true,
"-KkbS1pYW_9l4y4HPuog": true
}
}
}
}
成分的详细信息,即 name 取自字典:
{
"IngredientData": {
"ingredients": {
"-KkbS1pYW_9l4y4HPuog": {
"name": "Dough"
},
"-KkY8kL_wvxrcqMn_aP_": {
"name": "Mozzarella"
}
}
}
}
以下是用户添加自己的成分时的外观:
{
"users": {
"Ss5XNpWJ5IfIuYiMqsxTnMgjNrm1": {
"usersList": {
"-KlKuq2xjbQcR3ZMsHF1": {
"name": "Dough"
}
}
}
}
}
通过这种数据结构,我发现很难将用户成分列表的值与配方的成分列表进行比较。
我有一个Ingredient
类来处理用户成分中的属性,我也会在获取配方中的成分名称时使用它:
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)
}
}
我能够计算食谱中的成分数量,但现在我正在努力将其与用户成分列表进行比较。 ingredient.name
能够获取用户成分的名称,这是我想要用来比较它的内容,因为用户成分的关键是与食谱完全不同。
这是我在标签上显示的方式:
ingredientLbl.text = "\(recipe.matchedIngredients().0.count)/\(recipe.ingredients.count)"
答案 0 :(得分:0)
由于额外的查找,它变成了一个嵌套练习。但如果你仔细阅读循环,它实际上并不是那么困难。在JavaScript中,这可以解决问题:
ref.child("users").once("value").then((usersSnapshot) => {
usersSnapshot.forEach((userSnapshot) => {
ref.child("RecipeData").once("value").then((recipesSnapshot) => {
recipesSnapshot.forEach((recipeSnapshot) => {
var userNeeds = [];
recipeSnapshot.child("ingredients").forEach((recipeIngredientSnapshot) => {
userNeeds.push(ingredientsData[recipeIngredientSnapshot.key].name); // assume the user needs this
var recipeIngredientName = ingredientsData[recipeIngredientSnapshot.key];
userSnapshot.child("usersList").forEach((userIngredientSnapshot) => {
var index = userNeeds.indexOf(userIngredientSnapshot.val().name)
if (index >= 0) {
userNeeds.splice(index, 1);
}
});
console.log("User "+userSnapshot.key+" "+(userNeeds.length?"cannot":"can")+" make "+recipeSnapshot.key+": missing ingredients "+userNeeds);
});
});
});
});
});
工作的jsbin:https://jsbin.com/ziqobow/edit?js,console
我在这里做的不同的关键是我首先假设用户没有必要的成分,然后如果结果他们做已经有了这个成分那么就删除了这个假设