Home > database >  Flutter 2 dimensional List/Array as Int/Object(class)
Flutter 2 dimensional List/Array as Int/Object(class)

Time:11-29

I need a multidimensional array/list (2 and/or 3 dimensions) which must contains different objects. This is what I found:

  List recipes = List.generate(
      999,
      (_) => List<Ingredient>.filled(
          9,
          Ingredient(
              name: '', carboidrates: 0, proteins: 0, lipids: 0, fibers: 0),
          growable: true));

My needs is to have recipes[index/int][index/Ingredient].somethingoftheIngredientClass

As for example, if I create a single List:

List<Ingredient> recipe = <Ingredient>[];

I can access the class as

recipe[0].carboidrates

Not the same for my 2 dimensional list:

recipes[0][0].doesnotshowCarboidrates

CodePudding user response:

A list or multi-dimensional lists can only have a single type. Looking at your sample code, it looks like you're trying to associate ingredients and properties of a given recipe to a recipe using a multi-dimensional list.

A better approach would be to use classes. Classes will give you a more structured design and a little more flexibility. For example, the code below overrides the equality operator (==) and hashCode to be able to compare recipes and find a given recipe in a list.


class Recipe {
  final String name;
  final List<Ingredient> ingredients;
  final List<Instruction> instructions;

  Recipe({
    required this.name,
    required this.ingredients,
    required this.instructions,
  });

  @override
  bool operator ==(Object other) =>
      identical(this, other) || other is Recipe && runtimeType == other.runtimeType && name == other.name;

  @override
  int get hashCode => name.hashCode ^ ingredients.hashCode ^ instructions.hashCode;
}

class Ingredient {
  final String name;
  final String description;

  Ingredient({
    required this.name,
    required this.description,
  });
}

class Instruction {
  final String description;
  final String? tip;

  Instruction({
    required this.description,
    this.tip,
  });
}

final recipes = [
  Recipe(
    name: 'Cheese pizza',
    ingredients: [
      Ingredient(name: 'Dough', description: 'Normal yeast based pizza dough'),
      Ingredient(name: 'Tomato Sauce', description: 'Freshly blended organic tomatoes'),
      Ingredient(name: 'Mozzarella Cheese', description: 'Cheesy cheesiness from mount cheese'),
    ],
    instructions: [
      Instruction(description: 'Preheat oven to 400 degrees Fahrenheit'),
      Instruction(description: 'While oven is preheating spread dough evenly in a circle over an oiled pan'),
      Instruction(description: 'Spread sauce evenly over dough leaving enough room for the crust'),
      Instruction(description: 'Cover the sauce with the Mozzarella cheese'),
      Instruction(
        description: 'Roll the edge of the dough to form the crust',
        tip: 'Optionally add cheese within the dough for stuffed crust!',
      ),
      Instruction(description: 'Bake the pizza in the over until golden brown'),
      Instruction(
        description: 'Remove the pizza from the oven and let cool',
        tip: 'Some people like to let the pizza cool before cutting',
      ),
    ],
  ),
];

/// Find the index of a recipe. This uses the equality and hashcode overrides of the recipe class.
int getRecipeIndex(Recipe recipe) => recipes.indexOf(recipe);

/// Find all of the recipes containing the [query] in their name (case-insensitive).
List<Recipe> getRecipeByName(String query) {
  return recipes.where((element) => element.name.toLowerCase().contains(query.toLowerCase())).toList();
}

/// Get the ingredients of a recipe.
final recipeIngredients = recipes[0].ingredients;

/// Get the instructions of a recipe.
final recipeInstructions = recipes[0].instructions;

/// Get a list of all of the tips for a recipe.
final recipeTips = recipes[0].instructions.map((e) => e.tip).whereType<String>();

If for whatever reason you wanted to associate a recipe with a list of recipes (e.g. similar recipes) I would use a map of Recipe to List<Recipe>.

final pizza = recipes[0];

/// How to associate a recipe with similar recipes using a map of `Recipe` to `List<Recipe>`
final similarRecipesMap = { pizza: [recipes[1], recipes[2]]};

final similarRecipesToPizza = similarRecipesMap[pizza];

Hope that helps!

CodePudding user response:

Just found a programming 'bug'.

I tried to replicate my exactly code:

  List recipes = List.generate(
      999,
      (_) => List<Ingredient>.filled(
          9,
          Ingredient(
              name: 'Cheesecake',
              carboidrates: 0,
              proteins: 0,
              lipids: 0,
              fibers: 0),
          growable: true));

As you can see by adding 'Cheesecake' as the name.

In Init functions I just tried this:

print(recipes[0][0].name);

This work as expected, I accessed the value correctly...

Console Output:

Restarted application in 262ms.
flutter: Cheesecake

Really don't know why when I arrive at this point:

print(recipes[0][0].

Visual Studio Code does not show Class/Ingredient properties*, however it works!

*It shows only:

hashCode, runtimeType, toString(), noSuchMethod(...)

Really hope someone should explain why...

CodePudding user response:

Yup, another practical way to have 2d/3d list:

eg a 3d example:

  List<List<List<Ingredient>>> ingredient =
      List.generate(999, (index) => [[]], growable: true);

On Init function:

ingredient[0][0].clear();
ingredient[0][0].add(Ingredient(
    name: 'Panettone', carboidrates: 0, proteins: 0, lipids: 0, fibers: 0));
print(ingredient[0][0][0].name);

And now when I arrive here:

print(ingredient[0][0][0].

I finally should see the Ingredient Class properties (like name, carboidrates... and so on!)... WIN!

  • Related