Сравнение двух списков и фильтрация их элементов в Dart/Flutter?
Пытаюсь создать ExpansionList во Flutter: у меня созданы две модели CoffeeShop и CoffeeShopMenu, но загвоздка в том, что я хочу не просто списком выводить значения из модели CoffeeShopMenu, а чтобы каждому shopTitle было присвоено свое значение shopMenuTitle. Например: названию "Strarbucks" принадлежит 'Latte and americano', для 'Dunkin doghnuts' - 'Matcha' и т.д
Я эту задачу понимаю так: сначала нужно отфильтровать при помощи метода where каждый список, а затем уже отфильтрованное пропустить через метод forEach внутри виджета, где forEach идёт через каждый элемент модели CoffeeShop и ищет своей элемент в модели CoffeeShopMenu. Грубо говоря, я хочу отфильтровать оба списка со строковыми значениями по их тайтлам.
Но никак не могу понять, как это правильно реализовать и на данный момент код представляет из себя вот такое:
class ExpList extends StatelessWidget {
List<CoffeeShop> coffeeShop = <CoffeeShop>[
CoffeeShop(shopTitle: 'Strarbucks'),
CoffeeShop(shopTitle: 'Dunkin doghnuts'),
CoffeeShop(shopTitle: 'Subway'),
CoffeeShop(shopTitle: 'MCCafe'),
CoffeeShop(shopTitle: 'Coffee Shop'),
].where((element) => element.shopTitle == element.shopTitle).toList();
List<CoffeeShopMenu> coffeeMenu = <CoffeeShopMenu>[
CoffeeShopMenu(shopMenuTitle: 'Latte and americano'),
CoffeeShopMenu(shopMenuTitle: 'Matcha'),
CoffeeShopMenu(shopMenuTitle: 'pie'),
CoffeeShopMenu(shopMenuTitle: 'sandwich'),
CoffeeShopMenu(shopMenuTitle: 'croissant'),
].where((element) => element.shopMenuTitle == element.shopMenuTitle).toList();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: ListView.builder(
itemCount: coffeeShop.length,
itemBuilder: (context, index) {
coffeeShop.forEach((element) {
coffeeMenu.forEach((element) {
return coffeeMenu;
});
return coffeeShop;
});
return ExpansionTile(
title: Text(coffeeShop[index].shopTitle),
subtitle: Text(coffeeShop[index].shopTitle),
children: [
ListView.builder(
itemCount: coffeeMenu.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(coffeeMenu[index].shopMenuTitle)
);})],
);
}),
Также при попытке раскрыть список выходит ошибка:
Assertion failed:
hasSize
"RenderBox was not laid out: RenderViewport#6b2e7 NEEDS-PAINT"
Я так понимаю, это связано с тем, что я пытаюсь прогнать через второй ListView.builder список с меню?
Ответы (1 шт):
Вот простой пример как это можно сделать:
void main() {
final List<CoffeeShop> coffeeShop = <CoffeeShop>[
CoffeeShop(shopTitle: 'Strarbucks'),
CoffeeShop(shopTitle: 'Dunkin doghnuts'),
CoffeeShop(shopTitle: 'Subway'),
CoffeeShop(shopTitle: 'MCCafe'),
CoffeeShop(shopTitle: 'Coffee Shop'),
];
final List<CoffeeShopMenu> coffeeMenu = <CoffeeShopMenu>[
CoffeeShopMenu(shopMenuTitle: 'Latte and americano'),
CoffeeShopMenu(shopMenuTitle: 'Matcha'),
CoffeeShopMenu(shopMenuTitle: 'pie'),
CoffeeShopMenu(shopMenuTitle: 'sandwich'),
CoffeeShopMenu(shopMenuTitle: 'croissant'),
];
final List<Coffee> coffee = uniteCoffee(coffeeShop, coffeeMenu);
print(coffee);
print(coffee[1].menu.shopMenuTitle);
print(coffee[1].shop.shopTitle);
}
List<Coffee> uniteCoffee(List<CoffeeShop> coffeeShop, List<CoffeeShopMenu> coffeeMenu){
if(coffeeShop.length != coffeeShop.length) return [];
List<Coffee> temp = <Coffee>[];
for(int i = 0; i<coffeeShop.length; i++) {
temp.add(Coffee(coffeeShop[i], coffeeMenu[i]));
}
return temp;
}
class Coffee {
Coffee(this.shop, this.menu);
final CoffeeShop shop;
final CoffeeShopMenu menu;
@override
String toString() => "Coffee(shop: $shop, menu: $menu)";
}
class CoffeeShop {
CoffeeShop({this.shopTitle});
final String shopTitle;
@override
String toString() => "CoffeeShop(shopTitle: $shopTitle)";
}
class CoffeeShopMenu {
CoffeeShopMenu({this.shopMenuTitle});
final String shopMenuTitle;
@override
String toString() => "CoffeeShopMenu(shopMenuTitle: $shopMenuTitle)";
}
