Scala for推导式过滤失效:如何保留facetFilter中有效元素
修复Scala For推导式的FacetFilter过滤逻辑
你现在的需求是用Scala的for推导式生成修改后的facetFilter,把那些在facetFilter里但不存在于allFacets中的值过滤掉对吧?但目前你的newFacetFilter代码并没有实现这个过滤效果,咱们来看看问题出在哪,怎么改。
先看你给出的原始代码:
val allFacets = Map( "band_material" -> Map("Rubber" -> 11), "dial_color" -> Map("Ivory" -> 68, "Salmon"-> 3)) val facetFilter = Map("band_material" -> List("Yellow Gold Plated", "Rubber"), "dial_color" -> List("Ivory")) val newFacetFilter = for { (k,v) <- allFacets (facetName, facetArr) <- facetFilter aFacet <- facetArr if k != facetName || !v.contains(aFacet) } yield (facetName -> facetArr)
当前这段代码的输出是:
Map("band_material" -> List("Yellow Gold Plated", "Rubber"), "dial_color" -> List("Ivory"))
但你预期的输出应该是把band_material里的Yellow Gold Plated过滤掉,只保留存在于allFacets中的值:
Map("band_material" -> List("Rubber"), "dial_color" -> List("Ivory"))
问题分析
原来的for推导式逻辑完全走偏了——你现在的循环是同时遍历allFacets和facetFilter,最后还把原有的facetArr整个返回,根本没对列表里的元素做过滤。正确的思路应该是:针对facetFilter里的每个键值对,找到allFacets中对应的键,然后过滤出facetArr里存在于allFacets对应Map的键中的元素。
修正后的代码
我们可以调整for推导式的逻辑,或者更简洁地用map操作结合过滤:
方法一:用for推导式实现
val allFacets = Map( "band_material" -> Map("Rubber" -> 11), "dial_color" -> Map("Ivory" -> 68, "Salmon"-> 3)) val facetFilter = Map("band_material" -> List("Yellow Gold Plated", "Rubber"), "dial_color" -> List("Ivory")) val newFacetFilter = for { (facetName, facetArr) <- facetFilter validFacets = facetArr.filter(facet => allFacets.get(facetName).exists(_.contains(facet))) } yield (facetName -> validFacets)
方法二:更简洁的map写法
val newFacetFilter = facetFilter.map { case (name, values) => name -> values.filter(v => allFacets.get(name).exists(_.contains(v))) }
验证输出
这两种写法都会得到你预期的结果:
Map("band_material" -> List("Rubber"), "dial_color" -> List("Ivory"))
简单解释下逻辑:对facetFilter的每个条目,我们先通过allFacets.get(facetName)拿到对应的允许值集合(如果有的话),然后过滤当前的facetArr,只保留那些在允许集合里的元素。这样就实现了你要的过滤效果啦。
内容的提问来源于stack exchange,提问作者Avi Kaminetzky
相关产品推荐
相关产品推荐

