【问题标题】:Scala Collection filtering on multiple itemsScala Collection过滤多个项目
【发布时间】:2016-10-01 04:02:42
【问题描述】:

我有以下递归函数从列表中删除项目 (zooResidents: List[(String, Int)]) 包含在另一个列表 (pets: List[String] )。它可以工作,但速度很慢。 Scala 的实现方式是什么?

val pets = List("cat", "dog")

val zooResidents = List(("cat", 4), ("lion", 2), ("tiger", 3), ("dog", 2) 

def removePets(zooResidents: List[(String, Int)], pets: List[String]): List[(String, Int)] =  {
  if (pets.isEmpty) zooResidents
  else removePets(zooResidents.filterNot(_._1.contains(pets.head)), pets.tail)
}

removePets(zooResidents, pets)      //> res2: List[(String, Int)] = List((lion,2), (tiger,3))

【问题讨论】:

    标签: scala recursion functional-programming scala-collections tail-recursion


    【解决方案1】:

    请注意,List#contains 是线性的,因为它必须扫描整个列表,我建议您使用像 Set 这样的具有恒定时间查找的数据结构

    val petSet = pets.toSet
    val filter = zooResidents.filterNot(element => petSet.contains(element._1))
    

    【讨论】:

    • 苏莱曼。谢谢那行得通!我是 Scala 新手,您能帮我理解一下上面的工作原理吗?
    • 这根本无效,返回catdog,需要取反条件。
    • Lukasz,是的,我改为 filterNot。然后它会做我需要它做的事情。
    • 对不起,这是一个“错字”
    • @SaqibAli 我们只是过滤列表中的元素,对于每个元素,如果集合包含当前元素,我们不会将其添加到结果列表中。
    【解决方案2】:

    这就是我所说的scala方式

    @ zooResidents filterNot { case (resident, _) => pets contains resident } 
    res6: List[(String, Int)] = List(("lion", 2), ("tiger", 3))
    

    为了获得更好的性能,pets 应该是 Set

    filterNot 只接受那些不满足谓词的元素,即给定函数返回false 的那些元素。所以我们要取所有那些pets 不包含元组第一个元素的元素。

    你可以使用模式匹配而不是常规函数来解构元组,就像我做的那样

    { case (resident, _) => pets contains resident } 
    

    这等价于

    (residentTuple => pets.contains(residentTuple._1))
    

    【讨论】:

      【解决方案3】:
      val zooResidents = List(("cat", 4), ("lion", 2), ("tiger", 3), ("dog", 2)
      val pets = List("cat", "dog")
      

      试试这个单行:

      zooResidents.filter(x=>pets.toSet.contains(x._1)==false)
      
      scala> zooResidents.filter(x=>pets.toSet.contains(x._1)==false)
      res167: List[(String, Int)] = List((lion,2), (tiger,3))
      

      pets 改为 Set 以供表演。

      这需要 zooResidents 列表并检查 pets 中每个字符串是否存在,并仅返回 zooResidents 中不在 pets 中的元素,==false 将执行此操作。

      【讨论】:

      • 请补充说明。
      猜你喜欢
      • 2014-12-19
      • 1970-01-01
      • 2011-06-08
      • 1970-01-01
      • 2012-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多