如何按AvailableService过滤嵌套结构的Restaurant对象并返回同类型对象
Filter Restaurant Object by AvailableService Properties in Flutter
问题背景
我现在有这样一组Dart类定义:
class Restaurant{ List<Menu> menus; } class Menu { List<SubMenu> subMenus; } class SubMenu { AvailableService availableService; } class AvailableService { bool collection; bool delivery; bool table; }
已经实例化了Restaurant restaurant = Restaurant();,数据加载完成后每个SubMenu的服务属性都不同。现在需要实现一个过滤功能,比如得到仅包含支持配送(delivery为true)的SubMenu的新Restaurant对象,该怎么处理呢?
解决思路 & 代码实现
核心思路是递归过滤每一层数据,同时创建新对象避免修改原数据(防止副作用)。我们需要依次处理Restaurant→Menu→SubMenu这三层结构,只保留符合条件的子项,并且过滤掉空的Menu(避免保留没有有效SubMenu的菜单)。
1. 针对配送服务的专属过滤方法
如果只需要过滤支持配送的项,可以直接写一个专用方法:
Restaurant filterRestaurantForDelivery(Restaurant original) { // 过滤所有Menu,只保留包含符合条件SubMenu的Menu List<Menu> filteredMenus = original.menus?.where((menu) { // 过滤当前Menu下的SubMenu,仅保留delivery为true的 List<SubMenu> validSubMenus = menu.subMenus?.where((subMenu) { return subMenu.availableService?.delivery == true; }).toList() ?? []; // 如果过滤后还有有效SubMenu,就返回一个更新了subMenus的新Menu对象 if (validSubMenus.isNotEmpty) { return Menu(subMenus: validSubMenus); } // 否则过滤掉这个Menu return null; }).whereType<Menu>().toList() ?? []; // 返回包含过滤后菜单的新Restaurant对象 return Restaurant(menus: filteredMenus); }
2. 通用过滤方法(支持任意服务条件)
如果需要灵活支持不同的过滤规则(比如过滤支持到店取餐、同时支持配送+到店等),可以把过滤条件抽成参数,让方法更通用:
Restaurant filterRestaurant(Restaurant original, bool Function(AvailableService) filterRule) { List<Menu> filteredMenus = original.menus?.where((menu) { List<SubMenu> validSubMenus = menu.subMenus?.where((subMenu) { // 用传入的规则判断是否保留当前SubMenu return filterRule(subMenu.availableService!); }).toList() ?? []; if (validSubMenus.isNotEmpty) { // 注意:如果你的Menu类有其他属性(比如name、id),这里要把这些属性也复制过来 return Menu(subMenus: validSubMenus); } return null; }).whereType<Menu>().toList() ?? []; return Restaurant(menus: filteredMenus); }
使用示例
// 过滤仅支持配送的Restaurant Restaurant deliveryOnlyRestaurant = filterRestaurant(restaurant, (service) => service.delivery == true); // 过滤仅支持到店取餐的Restaurant Restaurant collectionOnlyRestaurant = filterRestaurant(restaurant, (service) => service.collection == true); // 过滤同时支持配送和到店取餐的Restaurant Restaurant dualServiceRestaurant = filterRestaurant(restaurant, (service) => service.delivery && service.collection);
注意事项
- 空值处理:代码里用
?? []处理了可能的空列表情况,你可以根据自己的业务逻辑调整空值判断(比如是否允许保留空Menu) - 对象不可变性:我们始终创建新的
Menu和Restaurant对象,不会修改原实例的数据,避免了意外的副作用 - 类属性扩展:如果你的
Menu或Restaurant有其他业务属性(比如restaurantName、menuId等),记得在创建新对象时把这些属性一并复制,避免丢失数据
内容的提问来源于stack exchange,提问作者flutter
相关产品推荐
相关产品推荐

