I have a list, I need to count the number of groups of certain elements(1 or 0).
(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1)
val count1Grp = daysSequence.foldLeft(List[Int]()){(acc, elem) =>
if(acc.isEmpty) elem :: acc else if(acc.head == elem) acc else elem :: acc
}
.count(_ == 1)
val count0Grp = daysSequence.foldLeft(List[Int]()){(acc, elem) =>
if(acc.isEmpty) elem :: acc else if(acc.head == elem) acc else elem :: acc
}
.count(_ == 0)
I fold similar neighbour elements and then do a count of what is left. And get
count1Grp = 1
count0Grp = 1
Another example. Both rows same result.
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
(-1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)
count1Grp = 1
count0Grp = 2
But how should I do it if I needed 2 or more similar elements together to quantify as a group? In the first case 0 wouldn't fit the criteria and should result in
count1Grp = 1
count0Grp = 0
CodePudding user response:
Why not get a Map
with a count of every group in the collection? Then only one traversal is needed.
def groupCount[A](xs : Seq[A]
,grpSize : Int = 1
,acc : Map[A,Int] = Map[A,Int]()
): Map[A,Int] = xs match {
case Seq() => acc
case hd : _ =>
val (grp,rest) = xs.span(_ == hd)
if (grp.size < grpSize)
groupCount(rest, grpSize, acc)
else
groupCount(rest, grpSize, acc (hd -> (acc.getOrElse(hd,0) 1)))
}
Here's a Scastie session with a few usage examples.