4

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

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

并且 valrepeats将等于2

显然上面是伪代码,takeWhile不会找到两个重复3的s,因为_它代表一个整数。我尝试将两者混合takeWhiletake(2)但收效甚微。我还参考了How to find count of repeatable elements in scala list 中的代码,但似乎作者正在寻求不同的东西。

谢谢你的帮助。

4

6 回答 6

5

这将在这种情况下工作:

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

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

问题是它是否为 List(3, 3, 3) 创建了正确的结果?您希望它是 2 次还是仅 1 次重复。

于 2013-09-28T05:24:54.833 回答
1
val repeats = list.sliding(2).toList.count(_==List(3,3))

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

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.
于 2018-07-12T04:32:33.410 回答
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为所需的尺寸。

于 2013-09-28T15:52:12.067 回答
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

Where runLength is defined as below from scala's 99 problems problem 9 and scala's 99 problems problem 10.

Since numberOfNs and runLengthPerN are Maps, you can get the population count of any number in the list with numberOfNs(number) and the length of the longest repitition in succession with runLengthPerN(number). To get the runLength, just compute as above with runLength(list).map{ t => t._2 -> t._1 }.

于 2013-09-27T23:40:33.570 回答
0

如果您知道您的列表不是很长,您可以使用Strings来完成。

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
于 2013-09-28T11:03:42.693 回答
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) }

我并不完全满意我需要使用可变 varn来计算出现次数,但它确实成功了。这将计算一个数字重复自身的次数,无论它重复多少次。

于 2013-09-27T23:55:47.433 回答