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!