lioli
lioli

Reputation: 191

How to count characters of a String?

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

Answers (5)

curious
curious

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

The Archetypal Paul
The Archetypal Paul

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

cmbaxter
cmbaxter

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 Chars 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

Ende Neu
Ende Neu

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

Seth Tisue
Seth Tisue

Reputation: 30453

You were close:

val s = "hello"
val list = s.toList.distinct
list.foreach(c => println(s.count(_ == c)))

I've changed your vars to vals, since there's no reason for them to be vars.

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

Related Questions