Search code examples
dartsetcontains

Check sets contain/match the set of a set in Dart


A sets receipt is a set of sets:

Set dish1 = {'a', 'b'};
Set dish2 = {'c', 'd'};
Set dish3 = {'a', 'b', 'c'};
Set dish4 = {'a', 'b', 'c', 'd'};
Set receipt = {dish1, dish2, dish3, dish4};

I would like to find the logic that can test whether a material belongs to a certain dish of above receipt.

Set material1 = {'a', 'b'}; // return dish1
Set material2 = {'a', 'b', 'c'}; // dish3
Set material3 = {'a', 'b', 'd'}; // null
Set material4 = {'b', 'c', 'a'}; // dish3

material3 {'a', 'b', 'd'} returns null not the dish1 because I'm looking for an exact element match but the order doesn't matter so material4 {'b', 'c', 'a'} can return dish3.

Thank you.


Solution

  • To be able to have dish1, dish2, etc. available for your result, they actually have to be in your program. You can do this with a Map.

    void main() {
      var receipt = {
        'dish1': {'a', 'b'},
        'dish2': {'c', 'd'},
        'dish3': {'a', 'b', 'c'},
        'dish4': {'a', 'b', 'c', 'd'},
      };
    
      var availableIngredients = {'b', 'c', 'a'};
    
      var dishesWithAvailableIngredients = receipt
        .entries
        .where(
          (entry) => entry.value.containsAll(availableIngredients)
        )
        .map((entry) => entry.key);
        
      print(dishesWithAvailableIngredients);
    }
    

    Of course, it might be nice to have some more structured data model in place:

    void main() {
      var receipt = new Receipt([
        new Dish(name: 'dish1', ingredients: {'a', 'b'}),
        new Dish(name: 'dish2', ingredients: {'c', 'd'}),
        new Dish(name: 'dish3', ingredients: {'a', 'b', 'c'}),
        new Dish(name: 'dish4', ingredients: {'a', 'b', 'c', 'd'}),
      ]);
      print(receipt.dishesWithIngredients({'b', 'c', 'a'}));
    }
    
    class Dish {
      // Might also want to track quantity, but I'm leaving that out
      String name;
      Set<String> ingredients;
    
      Dish({String name, Set<String> ingredients}) {
        this.name = name;
        this.ingredients = ingredients;
      }
    
      bool containsAll(Set<String> ingredients) {
        return this.ingredients.containsAll(ingredients);
      }
    
      String toString() {
        return "Dish(name: ${name}, ingredients: ${ingredients})";
      }
    }
    
    class Receipt {
      List<Dish> dishes;
    
      Receipt(List<Dish> dishes) {
        this.dishes = dishes;
      }
    
      Iterable<Dish> dishesWithIngredients(Set<String> ingredients) {
        return dishes.where((d) => d.containsAll(ingredients));
      }
    
      String toString() {
        return "Receipt(dishes: ${dishes})";
      }
    }