Reputation: 191
I am a pretty newbie to Scala! I would like to count the times a char occurs in a string. How do I do this? I started writing something like this but I find the syntax very hard to grasp. Any help?
var s = "hello"
var list = s.toList.distinct
list.foreach(println(s.count(_=='list')))
Upvotes: 5
Views: 9590
Reputation: 2928
Try This :
A tip, Don't use vars.
val l = "hello"
scala> l.distinct.toCharArray.map(x=>(x,l.count(_==x)))
res1: Array[(Char, Int)] = Array((h,1), (e,1), (l,2), (o,1))
It returns an array of (Char, Int)
map containing character and its associated count with it.
Upvotes: 4
Reputation: 41749
Or, as a illustration of "there's more than one way to do it"
var s = "hello"
s.foldLeft(Map[Char, Int]() withDefaultValue 0)
{(acc, c) => acc updated (c, acc(c)+1)}
//> res0: scala.collection.immutable.Map[Char,Int] =
Map(h -> 1, e -> 1, l -> 2, o -> 1)
and using a couple more features of Scala. This is basically the same as the groupBy/mapValues answers, except doing it in one pass.
Upvotes: 1
Reputation: 35443
You could try something like this if you wanted a Map of the chars to the counts:
val str = "hello"
val countsMap:Map[Char,Int] =
str.
groupBy(identity).
mapValues(_.size)
Which would expand to the more longhand form:
str.
groupBy(c => c).
mapValues(str => str.size)
So to break this down, in the groupBy
we are saying that we want to group by the individual Char
s in the String themselves. This will produce a Map[Char, String]
like so:
Map(e -> e, h -> h, l -> ll, o -> o)
Then, you re-map the values portion of that Map
with the mapValues
method telling it to use the .size
of the String
and not the String
itself.
Upvotes: 15
Reputation: 15783
You can easily group the characters using groupBy
and then measure the length:
scala> "hello".toList.groupBy(identity)
res0: scala.collection.immutable.Map[Char,List[Char]] = Map(e -> List(e), h -> List(h), l -> List(l, l), o -> List(o))
scala> res0.map { case (char, list) => (char, list.length) }
res1: scala.collection.immutable.Map[Char,Int] = Map(e -> 1, h -> 1, l -> 2, o -> 1)
Upvotes: 1
Reputation: 30453
You were close:
val s = "hello"
val list = s.toList.distinct
list.foreach(c => println(s.count(_ == c)))
I've changed your var
s to val
s, since there's no reason for them to be var
s.
Note that there isn't really any reason to convert your String
to a List
. It still works if you don't:
val s = "hello"
s.distinct.foreach(c => println(s.count(_ == c)))
Upvotes: 2