【问题标题】:How in Scala to find unique items in List如何在 Scala 中查找 List 中的唯一项目
【发布时间】:2009-10-08 15:37:38
【问题描述】:

如何在 Scala 中查找 List 中的唯一项?

【问题讨论】:

    标签: scala


    【解决方案1】:

    在 2.8 中,它是:

    List(1,2,3,2,1).distinct  // => List(1, 2, 3)
    

    【讨论】:

    • 恕我直言,1 和 2 不是列表中的唯一项目。只有3个。您从列表中创建一个独特项目的列表,这是另一回事。
    • 如果这是您想要的(通常不是),请使用:List(1,2,3,2,1).groupBy(x=>x).filter(_._2.lengthCompare (1) == 0).keySet
    【解决方案2】:

    最有效的保单方式是使用Set作为辅助数据结构:

    def unique[A](ls: List[A]) = {
      def loop(set: Set[A], ls: List[A]): List[A] = ls match {
        case hd :: tail if set contains hd => loop(set, tail)
        case hd :: tail => hd :: loop(set + hd, tail)
        case Nil => Nil
      }
    
      loop(Set(), ls)
    }
    

    我们可以使用隐式转换将其包装成更好的语法:

    implicit def listToSyntax[A](ls: List[A]) = new {
      def unique = unique(ls)
    }
    
    List(1, 1, 2, 3, 4, 5, 4).unique    // => List(1, 2, 3, 4, 5)
    

    【讨论】:

    • 现在太复杂了。 Scala 2.7 再好不过了。
    【解决方案3】:

    滚动您自己的具有订单保留功能的 uniq 过滤器:

    scala> val l = List(1,2,3,3,4,6,5,6)
    l: List[Int] = List(1, 2, 3, 3, 4, 6, 5, 6)
    
    scala> l.foldLeft(Nil: List[Int]) {(acc, next) => if (acc contains next) acc else next :: acc }.reverse
    res0: List[Int] = List(1, 2, 3, 4, 6, 5)
    

    【讨论】:

    • 我真的很喜欢这个,因为它允许复杂的过滤逻辑。谢谢!
    【解决方案4】:

    如果您参考Rosetta Code: Create a Sequence of unique elements

    val list = List(1,2,3,4,2,3,4,99)
    val l2 = list.removeDuplicates
    // l2: scala.List[scala.Int] = List(1,2,3,4,99)
    

    由于List 是不可变的,因此您不会通过调用removeDuplicates 来修改初始的List

    警告:正如this tweet(!) 所述,这不会保留顺序:

    scala> val list = List(2,1,2,4,2,9,3)
    list: List[Int] = List(2, 1, 2, 4, 2, 9, 3)
    
    scala> val l2 = list.removeDuplicates
    l2: List[Int] = List(1, 4, 2, 9, 3)
    

    根据ticket 929,对于Seq,该方法应该在Scala2.8 中可用。
    同时,您需要定义一个 ad-hoc 静态方法为 one seen here

    【讨论】:

    • 如果我有Seq[String] not List怎么办?
    • 显然是致电toList :) 或者,如@Synesso 所建议,使用foldLeft
    【解决方案5】:

    恕我直言,问题的所有解释都是错误的:

    如何在 Scala 中查找 List 中的唯一项?

    鉴于此列表:

    val ili = List (1, 2, 3, 4, 4, 3, 1, 1, 4, 1) 
    

    列表中唯一唯一的项目是2。其他项目不是唯一的。

    ili.toSet.filter (i => ili.indexOf (i) == ili.lastIndexOf (i))
    

    会找到的。

    【讨论】:

    • 大多数 java/scala 开发人员会将“给定列表中的唯一项目”的问题翻译为“给定列表中的所有不同值”而不是“在给定列表中单独显示的所有值”。 . 这是您之前的每个答案的解释方式,以及提出问题的人(谁批准了这样的答案)。 2 年多后出现并在解析已回答的问题时更加敏感会增加什么?
    • @mujimu:我不记得为什么两年后我偶然发现了这个问题。也许 sombebody 关闭了一个与完全重复的类似问题并在此处链接。在寻找其他人的解决方案之前,我经常尝试自己回答这些问题作为练习;他们是否有类似或更好的解决方案,或者发布我的解决方案是否有意义。所以我发现其他人回答了一个不同的问题。在知道其他人对这个问题的理解不同之后,我仍然认为该术语是错误的。一个句子的意思不应该由多数来判断。
    【解决方案6】:
    list.filter { x => list.count(_ == x) == 1 }
    

    【讨论】:

      【解决方案7】:

      一个简单的临时方法就是将列表添加到一个集合中,然后从那里使用:

        val l = List(1,2,3,3,3,4,5,5,6,7,8,8,8,9,9)
        val s = Set() ++ x
        println(s)
      

      生产:

      > Set(5, 1, 6, 9, 2, 7, 3, 8, 4)
      

      这适用于 Seq(或任何 Iterable),但在 2.8 中不是必需的,其中 removeDuplicates 方法可能更具可读性。此外,不确定运行时性能与更深思熟虑的转换。

      另外,请注意丢失的订单。

      【讨论】:

        【解决方案8】:

        list.toSet 会这样做,因为根据定义,Set 只包含唯一元素

        【讨论】:

        • 这在 5 年前的上一个答案中被指出,你的意思是什么?
        猜你喜欢
        • 2011-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-30
        • 2018-12-29
        相关资源
        最近更新 更多