如何在Scala列表中找到重复的项目?

时间:2013-09-27 22:23:27

标签: scala

我有一个包含重复数字的Scala列表。我想计算特定数字重复的次数。例如:

val list = List(1,2,3,3,4,2,8,4,3,3,5)
val repeats = list.takeWhile(_ == List(3,3)).size

val repeats等于2

显然上面是伪代码,takeWhile将找不到两个重复的3,因为_代表一个整数。我尝试混合takeWhiletake(2),但收效甚微。我还引用了How to find count of repeatable elements in scala list的代码,但似乎作者希望实现不同的东西。

感谢您的帮助。

6 个答案:

答案 0 :(得分:4)

这适用于这种情况:

val repeats = list.sliding(2).count(_.forall(_ == 3))

sliding(2)方法为您提供元素和后继列表的迭代器,然后我们只计算这两个等于3的位置。

问题是它是否为List(3,3,3)创建了正确的结果?你想要那个是2还是只重复1次。

答案 1 :(得分:1)

val repeats = list.sliding(2).toList.count(_==List(3,3))

更一般地,以下代码返回element的元组并为所有元素重复值:

scala> list.distinct.map(x=>(x,list.sliding(2).toList.count(_.forall(_==x))))
res27: List[(Int, Int)] = List((1,0), (2,0), (3,2), (4,0), (8,0), (5,0))

这意味着元素“ 3”在2个位置连续重复2次,其他所有元素重复0次。

而且,如果我们希望元素连续重复3次,则只需修改代码,如下所示:

list.distinct.map(x=>(x,list.sliding(3).toList.count(_.forall(_==x))))

在SCALA REPL中:

scala> val list = List(1,2,3,3,3,4,2,8,4,3,3,3,5)
list: List[Int] = List(1, 2, 3, 3, 3, 4, 2, 8, 4, 3, 3, 3, 5)

scala> list.distinct.map(x=>(x,list.sliding(3).toList.count(_==List(x,x,x))))
res29: List[(Int, Int)] = List((1,0), (2,0), (3,2), (4,0), (8,0), (5,0))

即使滑动值也可以通过定义以下函数来改变:

def repeatsByTimes(list:List[Int],n:Int) =
list.distinct.map(x=>(x,list.sliding(n).toList.count(_.forall(_==x))))

现在处于REPL:

scala> val list = List(1,2,3,3,4,2,8,4,3,3,5)
list: List[Int] = List(1, 2, 3, 3, 4, 2, 8, 4, 3, 3, 5)

scala> repeatsByTimes(list,2)
res33: List[(Int, Int)] = List((1,0), (2,0), (3,2), (4,0), (8,0), (5,0))

scala> val list = List(1,2,3,3,3,4,2,8,4,3,3,3,2,4,3,3,3,5)
list: List[Int] = List(1, 2, 3, 3, 3, 4, 2, 8, 4, 3, 3, 3, 2, 4, 3, 3, 3, 5)

scala> repeatsByTimes(list,3)
res34: List[(Int, Int)] = List((1,0), (2,0), (3,3), (4,0), (8,0), (5,0))

scala>

我们可以走得更远,就像给出整数列表和给出最大数量一样  在列表中任何元素都可以发生的连续重复中,我们可能需要一个由3个元组组成的列表来表示(该元素,该元素的重复次数,此重复发生在多少个位置)。这是比上述更详尽的信息。可以通过编写如下函数来实现:

 def repeats(list:List[Int],maxRep:Int) =
 { var v:List[(Int,Int,Int)] = List();
 for(i<- 1 to maxRep)
 v = v ++ list.distinct.map(x=> 
 (x,i,list.sliding(i).toList.count(_.forall(_==x))))
 v.sortBy(_._1) }

在SCALA REPL中:

scala> val list = List(1,2,3,3,3,4,2,8,4,3,3,3,2,4,3,3,3,5)
list: List[Int] = List(1, 2, 3, 3, 3, 4, 2, 8, 4, 3, 3, 3, 2, 4, 3, 3, 3, 5)


scala> repeats(list,3)
res38: List[(Int, Int, Int)] = List((1,1,1), (1,2,0), (1,3,0), (2,1,3), 
 (2,2,0), (2,3,0), (3,1,9), (3,2,6), (3,3,3), (4,1,3), (4,2,0), (4,3,0), 
 (5,1,1), (5,2,0), (5,3,0), (8,1,1), (8,2,0), (8,3,0))

scala>

这些结果可以理解如下:

   1 times the element '1' occurred at 1 places.
   2 times the element '1' occurred at 0 places.
   ............................................
   ............................................
   .............................................
   2 times the element '3' occurred at 6 places..
   .............................................
   3 times the element '3' occurred at 3 places...
   ............................................and so on.

答案 2 :(得分:0)

def pack[A](ls: List[A]): List[List[A]] = {
  if (ls.isEmpty) List(List())
  else {
    val (packed, next) = ls span { _ == ls.head }
    if (next == Nil) List(packed)
    else packed :: pack(next)
  }
}

def encode[A](ls: List[A]): List[(Int, A)] = pack(ls) map { e => (e.length, e.head) }

val numberOfNs = list.distinct.map{ n =>
  (n -> list.count(_ == n))
 }.toMap

val runLengthPerN = runLengthEncode(list).map{ t => t._2 -> t._1}.toMap

val nRepeatedMostInSuccession = runLengthPerN.toList.sortWith(_._2 <= _._2).head._1

其中runLength的定义如下scala's 99 problems problem 9scala's 99 problems problem 10

由于numberOfNsrunLengthPerNMaps,您可以使用numberOfNs(number)获取列表中任意数字的人口数,并连续获取最长重复次数的长度runLengthPerN(number)。要获得runLength,只需使用runLength(list).map{ t => t._2 -> t._1 }进行计算。

答案 3 :(得分:0)

感谢Luigi Plinge我能够使用游程编码中的方法将重复列表中的项目组合在一起。我在此处使用了此页面中的一些代码段:http://aperiodic.net/phil/scala/s-99/

var n = 0
runLengthEncode(totalFrequencies).foreach{ o => 
  if(o._1 > 1 && o._2==subjectNumber) n+=1
}
n

方法runLengthEncode如下:

  private def pack[A](ls: List[A]): List[List[A]] = {
    if (ls.isEmpty) List(List())
    else {
      val (packed, next) = ls span { _ == ls.head }
      if (next == Nil) List(packed)
      else packed :: pack(next)
    }
  }

  private def runLengthEncode[A](ls: List[A]): List[(Int, A)] =
    pack(ls) map { e => (e.length, e.head) }

我不完全满意我需要使用mutable var n来计算出现次数,但它确实有效。这将计算一个数字重复的次数,无论它重复多少次。

答案 4 :(得分:0)

如果您知道列表不长,则可以使用字符串来完成。

val list = List(1,2,3,3,4,2,8,4,3,3,5)
val matchList = List(3,3)
(matchList.mkString(",")).r.findAllMatchIn(list.mkString(",")).length

答案 5 :(得分:0)

从你的伪代码我得到了这个工作:

val pairs = list.sliding(2).toList  //create pairs of consecutive elements
val result = pairs.groupBy(x => x).map{ case(x,y) => (x,y.size);   //group pairs and retain the size, which is the number of occurrences.

result将是Map[List[Int], Int],因此您可以将计数数字视为:

 result(List(3,3))    // will return 2 

我无法理解您是否还要查看多个尺寸的列表,然后您需要将参数更改为sliding到所需的尺寸。