2015-11-19 72 views
0

集合我有两个班“Receipe”和“Incredient”。 receipe可以有一个成员列表。现在,我希望当我通过一个不容易的名单时,我应该收回所有包含那个难以置信的收据。以下是我有:斯威夫特过滤基于另一个集合

如何过滤基于在incrediants传递的receipies。

class Recipe { 

    var name :String! 
    var incredients :[Incredient]! 

    init(name :String, incredients :[Incredient]) { 
     self.name = name 
     self.incredients = incredients 
    } 

} 

class Incredient { 
    var name :String! 

    init(name :String) { 
     self.name = name 
    } 
} 

var incredientsToSearchFor = [Incredient(name:"Salt"),Incredient(name :"Sugar")] 

var receipe1 = Recipe(name: "Receipe 1", incredients: [Incredient(name: "Salt"),Incredient(name :"Pepper"),Incredient(name :"Water"),Incredient(name :"Sugar")]) 

var receipe2 = Recipe(name: "Receipe 2", incredients: [Incredient(name: "Salt"),Incredient(name :"Pepper"),Incredient(name :"Water"),Incredient(name :"Sugar")]) 

var receipe3 = Recipe(name: "Receipe 3", incredients: [Incredient(name :"Pepper"),Incredient(name :"Water"),Incredient(name :"Sugar")]) 

var receipies = [receipe1,receipe2,receipe3] // list of all the recipies 

func getRecipiesByIncrediants(incredients :[Incredient]) -> [Recipe] { 

    // WHAT TO DO HERE 

    return nil 
} 

let matchedRecipies = getRecipiesByIncrediants(incredientsToSearchFor) 
+0

你的问题不清楚。当你将'Salt'和'Sugar'传递给'getRecipiesByIncrediants'时,你期望得到:(a)所有含有盐或糖的食谱; (b)所有含有盐和糖的食谱; (c)只有盐和糖的所有食谱,没有其他成分?还有大拼写错误:它的“成分”不是“难以置信” –

回答

1

有几件事情需要改变。

首先,这些是数据模型,所以它们应该可能是struct类型而不是class。这允许你删除初始化和自选太:

struct Recipe : Equatable { 
    let name: String 
    let ingredients: [Ingredient] 
} 

struct Ingredient : Equatable { 
    let name : String 
} 

你会发现我也让他们Equatable。这样可以使用contains在数组中找到它们。没有它,contains将不知道这两种类型是否相等。

为了符合Equatable,只需添加==方法:

func ==(lhs: Ingredient, rhs: Ingredient) -> Bool { 
    return lhs.name == rhs.name 
} 

func ==(lhs: Recipe, rhs: Recipe) -> Bool { 
    return lhs.name == rhs.name && lhs.ingredients == rhs.ingredients 
} 

创建你的数据是大致相同的。我修正了一些拼写错误,并改变varlet因为这些值不会改变:

let ingredientsToSearchFor = [Ingredient(name:"Salt"), Ingredient(name :"Sugar")] 

let recipe1 = Recipe(name: "Recipe 1", ingredients: [Ingredient(name: "Salt"), Ingredient(name :"Pepper"), Ingredient(name :"Water"), Ingredient(name :"Sugar")]) 

let recipe2 = Recipe(name: "Recipe 2", ingredients: [Ingredient(name: "Salt"), Ingredient(name :"Pepper"), Ingredient(name :"Water"), Ingredient(name :"Sugar")]) 

let recipe3 = Recipe(name: "Recipe 3", ingredients: [Ingredient(name :"Pepper"), Ingredient(name :"Water"), Ingredient(name :"Sugar")]) 

let recipes = [recipe1, recipe2, recipe3] // list of all the recipes 

现在到过滤。还有更有效的方法可以做到这一点,但为了便于阅读,您可以使用filterreduce

func getRecipesByIngredients(incredients :[Ingredient]) -> [Recipe] { 
    return recipes.filter { recipe in 
     incredients.reduce(true) { currentValue, ingredient in 
      return currentValue && (recipe.ingredients.contains(ingredient)) 
     } 
    } 
} 

filter返回一个只包含元素的新数组,其中块11返回truereduce合并整个阵列成一个值(在这种情况下truefalse)。因此,我们遍历每个配方,并检查是否所有指定的成分都在其中。

要调用方法:

let matchedRecipes = getRecipesByIngredients(ingredientsToSearchFor) 

这返回配方1和2,因为两者都含有盐和糖。

如果您想要含有盐或糖的食谱,请使用reduce(false)并将&&更改为||