I'm new to Scala and doing my best to solve and practice a lot. I have faced a problem while practicing and found no solution.
var list = List("Scala","combines","object-
oriented","and","functional","programming","in","one","concise",
"high-level", "language")
def getCount(inputStr: List[String]): Int = {
val vowelsList = List('a', 'e', 'i', 'o', 'u')
inputStr.map(x => x.contains(vowelsList)).length
}
getCount(list)
// Expected Output = 32
// Output = 11
I know it counts only the words, but how is it possible to iterate at every possible char and check if it's a vowel or not? (in Scala)
CodePudding user response:
Here's a more lower-level way of doing it: just put a 1
in a list for every occurrence found and sum it up at the end:
def getCount(words: List[String]): Int = {
val listOfOnes = for {
word <- words
c <- word
if vowels.contains(c.toLower)
} yield 1
listOfOnes.sum
}
println(getCount(words)) // 32
There are a lot of ways to solve it, you should try solving it in more than one way to really get a feeling about how powerful the language is. Gael's idea is indeed much more elegant:
println(words.flatten.count(c => vowels.contains(c.toLower))) // 32
or
println(words.mkString.count(c => vowels.contains(c.toLower))) // 32
Say count
did not exist. You could do it, for example, like this:
println(words.flatten.foldLeft(0) { (acc, c) =>
if (vowels.contains(c.toLower)) acc 1 else acc
}) // 32
CodePudding user response:
In Scala, you can think of a string as a sequence of characters. In reality, in most Scala implementations, strings are actually implemented by the hosting platform (e.g. on the JVM, strings are actually JVM String
s and on Scala.js, they are actually ECMAScript string
s), but there are usually some implicit conversions and possibly some compiler trickery as well to make them look like they are native Scala types and implement all the native Scala collection APIs.
So, a list of strings is really two collections nested inside each other, and you can flatten these nested collections out to a single collection using the flatten
method:
list.flatten
//=> List(S, c, a, l, a, c, o, m, b, i, n, e, s, o, b, j, e, c, t, -, o, r, i, e, n, t, e, d, a, n, d, f, u, n, c, t, i, o, n, a, l, p, r, o, g, r, a, m, m, i, n, g, i, n, o, n, e, c, o, n, c, i, s, e, h, i, g, h, -, l, e, v, e, l, l, a, n, g, u, a, g, e)
Now that you have a flat list, you can just use the count
method to count the number of elements that satisfy a given predicate (i.e. a function from the element type to Boolean
).
A nice feature of Scala's collections API is that Set
s are actually predicates! I.e. a Set
object is actually a function which tells you whether an element is a member of the Set
.
If we combine those two features together, we end up with something like this:
val vowels = Set('a', 'e', 'i', 'o', 'u')
list.flatten.count(vowels)
//=> 32
CodePudding user response:
A similar solution to the count one is to filter the string for vowels and find its size:
"abcdefghijk".filter("aeiouAEIOU".contains(_)).size
The _
is an anonymous variable that simplifies c => [...].contains(c)
in the case that c
occurs only once in the expression.
CodePudding user response:
A simple solution is to just count the number of vowels of each word and then sum
the results.
def countVowels(words: List[String]): Int = {
val vowels = Set('a', 'e', 'i', 'o', 'u')
words.map(word => word.count(c => vowels.contains(c.toLower))).sum
}