如何使用Dart 3模式匹配匹配列表中非首尾元素
Dart模式匹配:匹配列表中指定元素的正确方式
首先明确:Dart的模式匹配可以实现你的需求,但确实不允许在列表模式中使用两个... rest元素,这是语法规则限制(报错提示的"At most one rest element is allowed"就是这个原因)。下面分场景给出具体实现方案:
1. 仅需匹配列表中存在目标元素(位置不限)
如果只需要判断列表里是否包含{"key2": true},不管它在首尾还是中间,最简洁的方式是结合switch的when子句,利用列表的contains方法做判断:
void checkHasTarget(List<Map<String, bool>> list) { switch (list) { case final l when l.contains({"key2": true}): print("列表包含目标元素"); default: print("列表不包含目标元素"); } }
如果你想尝试纯模式匹配的写法,可以拆分不同位置的情况(虽然不如contains简洁):
void checkHasTarget(List<Map<String, bool>> list) { switch (list) { case [{"key2": true}, ...]: // 目标是第一个元素 case [..., {"key2": true}]: // 目标是最后一个元素 case [_, {"key2": true}, ...]: // 目标在中间(列表长度≥2) print("列表包含目标元素"); default: print("列表不包含目标元素"); } }
2. 匹配目标元素既不是第一个也不是最后一个的场景
如果需要严格判断目标元素处于列表的中间位置(非首尾),需要满足三个条件:列表长度≥3、首尾元素不是目标、列表包含目标。结合模式匹配和when子句可以实现:
void checkMiddleTarget(List<Map<String, bool>> list) { switch (list) { case final l when l.length >= 3 && l.first != {"key2": true} && l.last != {"key2": true} && l.contains({"key2": true}): print("目标元素在列表中间(非首尾)"); case [{"key2": true}, ...]: print("目标是第一个元素"); case [..., {"key2": true}]: print("目标是最后一个元素"); default: print("列表不包含目标元素"); } }
如果是针对固定长度的列表(比如你给出的3元素列表),可以直接用固定位置的模式匹配:
void checkThreeElementList(List<Map<String, bool>> list) { switch (list) { case [_, {"key2": true}, _]: print("3元素列表中,目标在中间"); case [{"key2": true}, _, _]: print("3元素列表中,目标是第一个"); case [_, _, {"key2": true}]: print("3元素列表中,目标是最后一个"); default: print("3元素列表不包含目标"); } }
为什么不能用[..., {"key2":true}, ...]?
Dart的列表模式设计中,一个模式最多只能有一个... rest元素。这是因为多个rest元素会导致匹配逻辑歧义——编译器无法确定哪些元素属于前一个rest,哪些属于后一个rest,因此语法上直接禁止这种写法。
内容的提问来源于stack exchange,提问作者Bruno Viana
相关产品推荐
相关产品推荐

